Search code examples
iosobjective-cuiimagensdatansfilemanager

Why saving and loading UIImages in documents folder doesn't work properly in iOS 8+?


I've been trying to save and load UIImages in my app's Documents folder or preferably temp folder (so every time my app gets closed images will be deleted) but they aren't working correctly. I've tried three approaches but only the third approach works and i'm wondering what's the right way to do it? I highly appreciate any help.

 //First Approach, to save and load later, Doesn't work.
 //Saving the image
 NSURL *documentsDirectoryURL = [[[NSFileManager defaultManager]
                                  URLsForDirectory:NSDocumentDirectory
                                   inDomains:NSUserDomainMask]
                                    lastObject];
NSString*fileDirectoryStr = [[documentsDirectoryURL path] stringByAppendingPathComponent:@"E1BG.png"];
NSURL *url = [NSURL URLWithString:fileDirectoryStr];
//Saving either as Jpeg
[UIImagePNGRepresentation(finalFG) writeToFile:fileDirectoryStr atomically:YES];
//Or as PNG, because I need the transparent part to be kept transparent but non of them work.
[UIImageJPEGRepresentation(finalFG, 1.0) writeToFile:fileDirectoryStr atomically:YES];
//Loading image
UIImage *loadedBGImg = [UIImage imageWithData: [NSData dataWithContentsOfURL:url]];
//Returns nil

//Second approach.
//Saving the image
NSArray*pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsPath = [pathArray objectAtIndex:0];
NSString* fileDirectoryStr = [documentsPath stringByAppendingPathComponent:@"E1FG.png"];
//Again saving either as Jpeg
[UIImagePNGRepresentation(finalFG) writeToFile:fileDirectoryStr atomically:YES];
//Or as PNG, because I need the transparent part to be kept transparent but non of them work.
[UIImageJPEGRepresentation(finalFG, 1.0) writeToFile:fileDirectoryStr atomically:YES];
NSURL *url1 = [NSURL URLWithString:fileDirectoryStr];
//Loading image
UIImage *loadedImg = [UIImage imageWithData: [NSData dataWithContentsOfURL:url1]];

 //Third approach, Works but doesnt seem to be very efficient.
 NSString *tmpDirectory = NSTemporaryDirectory();
 //Save
 NSString *tmpFileStrFG = [tmpDirectory stringByAppendingPathComponent:@"E1FG.png"];
 NSURL *urlFG = [NSURL URLWithString:tmpFileStrFG];
 NSData *imgDataFG = UIImagePNGRepresentation(finalFG);
 [imgDataFG writeToURL:urlFG atomically:YES];
 //Load
 UIImage *ImggFG = [UIImage imageWithData: imgDataFG];

Solution

  • I have created class which allows to save in document folder

    Here is .h File

    @interface FileUtility : NSObject {
    
    }
    
    // Folder methods
    + (NSString*)basePath;
    + (void)createFile:(NSString *)filename;
    + (void)createFile:(NSString *)filePath withData: (NSData *) imgData;
    
    @end
    

    and .m File

    #import "FileUtility.h"
    
    @implementation FileUtility
    
    // ----------------------------------------------------------------------------
    
    #pragma mark -
    #pragma mark Path methods
    
    // -----------------------------------------------------------------------------
    
    + (NSString*)basePath {
        NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSAssert([paths count] == 1, @"");
        return [paths objectAtIndex:0];     
    }
    
    // -----------------------------------------------------------------------------
    
    
    
    
      + (void)createFile:(NSString *)filename {
        NSFileManager* manager = [NSFileManager defaultManager];
        NSString * filePath = [NSString stringWithFormat:@"%@/%@", [FileUtility basePath],filename];
        DLOG(@"filePath = %@", filePath);
        if (![FileUtility fileExists:filePath]){
            [manager createFileAtPath:filePath contents:nil attributes:nil];
        }
    
        }
    
    // -----------------------------------------------------------------------------
    
    + (void)createFile:(NSString *)filePath withData: (NSData *) imgData {
        NSFileManager* manager = [NSFileManager defaultManager];
        DLOG(@"filePath = %@", filePath);
        if (![FileUtility fileExists:filePath]){
            [manager createFileAtPath:filePath contents:imgData attributes:nil];
        }
    }
    

    For fetch use this

    [[FileUtility basePath] stringByAppendingPathComponent

    EDIT

    + (BOOL)fileExists:(NSString *)filename {
        NSFileManager* manager = [NSFileManager defaultManager];
        return [manager fileExistsAtPath:filename];
    }