Search code examples
iosobjective-cnsdatansdocumentdirectory

Objective C - writeToFile successful but removeFile returns error for same file


I am saving photos a user takes with UIImagePickerController to the user's documents directory. When the app successfully uploads the image to the server, I would like to delete the locally saved image.

I save the image to documents directory like this:

/*Save image to documents directory, as opposed to core data for better memory management*/
        NSString *myUniqueName = [NSString stringWithFormat:@"%lu.png", (unsigned long)([[NSDate date] timeIntervalSince1970]*10.0)];
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
        NSString *filePath = [documentsPath stringByAppendingPathComponent:myUniqueName]; //Add the file name

       BOOL successWriteLocalImage = [imageToUpload writeToFile:filePath options:NSDataWritingAtomic error:&error];

            if(successWriteLocalImage){
                //NSLog(@"no error success writing to file");
                NSLog(@"successfully write to file path %@", filePath);

            }else{
                NSLog(@"Unresolved error writing to file %@, %@", [error localizedDescription], [error userInfo]);
            }
        /*Save file path of leaf image to core data here*/
        collectedLeaf.localImageFilePath = filePath;

        [context save:&error];

I delete the same file like so:

/*delete image stored in documents directory from collecting w/o internet connection*/
NSFileManager *fileManager = [NSFileManager defaultManager];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:collectedLeaf.localImageFilePath];
NSError *error;
BOOL successDeleteLocalImage = [fileManager removeItemAtPath:filePath error:&error];
if(successDeleteLocalImage){
    NSLog(@"SUCCESS DELETE IMAGE NO ERROR");
    collectedLeaf.localImageFilePath = nil;
}else{
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}

The successful write/save to documents directory prints, successfully write to file path /var/mobile/Containers/Data/Application/EA08B79A-7484-4568-82CE-079B4055CDA7/Documents/15130563374.png.

The error in removing the file logs

Unresolved error Error Domain=NSCocoaErrorDomain Code=4 "“15130563374.png” couldn’t be removed." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/EA08B79A-7484-4568-82CE-079B4055CDA7/Documents/var/mobile/Containers/Data/Application/EA08B79A-7484-4568-82CE-079B4055CDA7/Documents/15130563374.png, NSUserStringVariant=(
), NSUnderlyingError=0x1c4a4b4c0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}, {
    NSUnderlyingError = "Error Domain=NSPOSIXErrorDomain Code=2 \"No such file or directory\"";

I'm not sure why the file can't be removed - or that it returns not found - when its the same exact file path as the one I write to.


Solution

  • Issue is pretty clear. The file where you saved the file is

    /var/mobile/Containers/Data/Application/EA08B79A-7484-4568-82CE-079B4055CDA7/Documents/15130563374.png
    

    And the location where you are trying to delete is

    /var/mobile/Containers/Data/Application/EA08B79A-7484-4568-82CE-079B4055CDA7/Documents/var/mobile/Containers/Data/Application/EA08B79A-7484-4568-82CE-079B4055CDA7/Documents/15130563374.png
    

    So clearly you are trying to delete image at wrong path.

    Issue:

     collectedLeaf.localImageFilePath = filePath;
    

    Saves the images absolute path and not the relative path. So

    NSString *filePath = [documentsPath stringByAppendingPathComponent:collectedLeaf.localImageFilePath];
    

    will append the absolute path of the image to document directory path hence results in issue

    Solution:

    Save just the unique name of file in core data

    collectedLeaf.localImageFilePath = myUniqueName;
    

    That should solve your issue

    Additional Piece of Information:

    Never ever save the absolute path of file in core data. Location of the document directory will change between app quit and launch. So saving absolute file path is not a option. Save file name and reconstruct URL from file name