Question

Is there any reason why writing and saving a PDF file to the Documents directory in an iOS application would only be intermittently successful? In my app I am created a PDF from an array of UIViews, accessing the Documents folder and storing the file in there.

I would estimate that this works 80% of the time. The other 20% of the time the PDF gets created (I also email it to myself which works) but it never actually get written to the Documents folder.

In the case of failure, I can email myself the PDF so I know it gets created. When I inspect the Documents folder in a file explorer it's empty. When I log out the contents of it it is also empty. I'm using the following code to create the PDF and export to Documents.

- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

-(void)createPDFfromUIViews:(NSArray *)views saveToDocumentsWithFileName:(NSString*)aFilename andTag:(NSInteger)tag
{
    // Creates a mutable data object for updating with binary data, like a byte array
    NSMutableData *pdfData = [NSMutableData data];

    // Points the pdf converter to the mutable data object and to the UIView to be converted
    UIView *view1 = [views objectAtIndex:0];
    UIGraphicsBeginPDFContextToData(pdfData, view1.bounds, nil);
    CGContextRef pdfContext = UIGraphicsGetCurrentContext();

    // draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
    for (UIView *view in views)
    {
        UIGraphicsBeginPDFPage();
        [view.layer renderInContext:pdfContext];
    }

    // remove PDF rendering context
    UIGraphicsEndPDFContext();

    // Get the path to the documents directory and append the filename of the PDF
    NSString *path = [[self applicationDocumentsDirectory].path stringByAppendingPathComponent:aFilename];

    NSLog (@"DOCUMENTS DIRECTORY : %@", [self applicationDocumentsDirectory].path);
    NSLog (@"DOCUMENTS DIRECTORY WITH FILE PATH : %@", path);

    NSError *error = nil;
    BOOL success = [pdfData writeToFile:path options:NSDataWritingWithoutOverwriting error:&error];

    if (!success)
    {
        NSLog(@"Error writing PDF: %@", [error localizedDescription]);
    }
    else
    {
        if (tag == 1)
        {
            NSLog(@"PDF Saved With Name %@", aFilename);
            [self.navigationController popViewControllerAnimated:YES];
        }
        else if (tag == 2)
        {
            [self checkAccountAndComposeEmailWithAttachmentData:pdfData andSubject:aFilename];
        }
    }

}

UPDATE: Code amended to include NSError. The error given is "The operation couldnt be completed. (Cocoa Error 4.)

UPDATE 2: Amended the code to include Apple's recommended method of grabbing the Documents directory. Also added in a number of logs to show that I am getting correct Directory / File Path - both are showing the Documents folder or the Documents/File Name as expected. Still returns NSFileNoSuchFileError as an error every time.

Was it helpful?

Solution

You probably should be writing with the API that allows you to pass an error pointer in

- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)mask error:(NSError **)errorPtr

Then, you can inspect the NSError if it does not write properly, and act intelligently with this info.

NSError *error = nil;
BOOL success = [pdfData writeToFile:documentDirectoryFilename options:NSDataWritingAtomic error:&error];
if (!success) {
    NSLog(@"Error writing: %@", [error localizedDescription]);
}

The specific error you have is a NSFileNoSuchFileError, a clue that perhaps there are spaces or some other non-supported character in the file path, amongst other reasons.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top