Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to create files in caches directory

I'm trying to set up a caches directory for use in my app, but the files are not being created for a reason unknown to me. What am I doing wrong? Here are the methods I'm using:

In class Utilities:

+(NSString *)imageCachePath {
   NSString *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
   NSString *pieceImagesDirectory = [cacheDirectory stringByAppendingPathComponent:@"PieceImages"];
   NSLog(@"imageCachPath is %@",pieceImagesDirectory);
   return pieceImagesDirectory;
}
+ (void)cacheImage:(UIImage *)image usingName:(NSString *)name;
{
   NSLog(@"Caching image %@",name);
   NSString *pieceImagesDirectory = [self imageCachePath];
   BOOL isDir = NO;
   NSError *error;
   if (! [[NSFileManager defaultManager] fileExistsAtPath:pieceImagesDirectory isDirectory:&isDir] && isDir == NO) {
      [[NSFileManager defaultManager]createDirectoryAtPath:pieceImagesDirectory withIntermediateDirectories:YES attributes:nil error:&error];
      NSLog(@"Error after creating directory:\n%@",error);
   } else {
      // file exists - I don't expect to use the else block. This is for figuring out what's going on.
      NSLog(@"File %@ exists -- is it a directory? %@",pieceImagesDirectory, isDir?@"YES":@"NO");
   }
   NSString *nameToUseInFilename = [name stringByReplacingOccurrencesOfString:@" " withString:@"_"];
   NSString *fullPath = [pieceImagesDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png",nameToUseInFilename]];
   NSData *data = UIImagePNGRepresentation(image);
   NSFileManager *fileManager = [NSFileManager defaultManager];
   //Save the file, overwrite existing if exists.
   NSLog(@"Attempting to create file at path %@ with %d bytes of data",fullPath, [data length]);
   if ([fileManager createFileAtPath:fullPath contents:data attributes:nil]) {
      NSLog(@"Success");
   } else {
      NSLog(@"Error creating file");
   }
}

In the class where the images are created, I call the method thus:

// image is an object of type UIImage
// cachedImageName is a string that resolves to something like User Image/12
[Utilities cacheImage:image usingName:cachedImageName];

Here are sample NSLog output lines in the debugger:

... Caching image User Image/12
... imageCachPath is /var/mobile/Applications/5EBB1152-5CC1-4A30-ABD5-B4C9A60E4CB4/Library/Caches/PieceImages
... File /var/mobile/Applications/5EBB1152-5CC1-4A30-ABD5-B4C9A60E4CB4/Library/Caches/PieceImages exists -- is it a directory? YES
... Attempting to create file at path /var/mobile/Applications/5EBB1152-5CC1-4A30-ABD5-B4C9A60E4CB4/Library/Caches/PieceImages/User_Image/12.png with 12071 bytes of data
... Error creating file
like image 989
Victor Engel Avatar asked Sep 29 '13 18:09

Victor Engel


1 Answers

The call to NSFileManager fileExistsAtPath:isDirectory: gives you an indeterminate value for isDir if the directory doesn't exist. You should change your code to:

BOOL isDir = NO;
NSError *error;
if (! [[NSFileManager defaultManager] fileExistsAtPath:pieceImagesDirectory isDirectory:&isDir]) {
    [[NSFileManager defaultManager]createDirectoryAtPath:pieceImagesDirectory withIntermediateDirectories:YES attributes:nil error:&error];
    NSLog(@"Error after creating directory:\n%@",error);
} else {
    // file exists - I don't expect to use the else block. This is for figuring out what's going on.
    NSLog(@"File %@ exists -- is it a directory? %@",pieceImagesDirectory, isDir?@"YES":@"NO");
}

It also appears that you add a second folder User_Image to the path. You never create this directory.

I would also suggest you change how you write the image data. Instead of using NSFileManager createFileAtPath:contents:attributes:, use NSData writeToFile:options:error:. Then you can get an error object providing more details of any problem.

In the end it may be best to build the full path to the file. Strip off the last path component (the actual filename) and then check for the existence of the remaining path. Then make one call to createDirectoryAtPath... and let it create any all all needed folders.

like image 81
rmaddy Avatar answered Oct 14 '22 13:10

rmaddy