Search code examples
iosobjective-cnsdatansfilemanagernsdocumentdirectory

UIImage saved to Document Directory returning nil


NSDocumentDirectoryI'm new to iOS. Im trying to build a simple app to better grasp Core Data and the file system. I can't retrieve data that I've apparently stored.

-I check to see if the file exists at the path, which it does, but when I try to NSLog the data and that returns null.

Any help is much appreciated. My gut is that this is a scoping or memory retention issue but I can't figure it out.

This is the saving method from UIImagePicker

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    UIImage *imageToAdd = info[UIImagePickerControllerOriginalImage];
    NSData *pngsData = UIImagePNGRepresentation(imageToAdd);
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docPath = [paths objectAtIndex:0];
    NSString *filePath = [docPath stringByAppendingFormat:@"%@.png",[self getdateAndTime]];
    NSError *error;
    BOOL succcess = [pngsData writeToFile:filePath options:NSDataWritingAtomic error:&error];
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        NSLog(@"The file exists");
    }

    if (error !=nil) {
        NSLog(@"errorIS %@", error);
    }

    CoreDataStack *cds = [CoreDataStack defaultStack];
    Photo *photo = [NSEntityDescription insertNewObjectForEntityForName:@"Photo" inManagedObjectContext:cds.managedObjectContext];
    photo.photoName = filePath;
    [cds saveContext];

    [self dismissViewControllerAnimated:YES completion:nil];
    [self.collectionView reloadData];
}

This is the code to retrieve the stored data the Collection View

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    PhotoCollectionViewCell *photoCell = (PhotoCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"photoCell" forIndexPath:indexPath];
    Photo *photo = [self.fetchedResultsController objectAtIndexPath:indexPath];
    NSLog(@"%@",photo.photoName);

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *imageLocation = [documentsDirectory stringByAppendingString:photo.photoName];
    NSData *data = [NSData dataWithContentsOfFile:imageLocation];
    UIImage *image = [UIImage imageWithData:self.testImageData];
    NSLog(@"%@", data);

    photoCell.cellImage.image = image;
    photoCell.layer.borderColor = [[UIColor blackColor] CGColor];
    photoCell.layer.borderWidth = 2.0;

    return photoCell;
}

Solution

  • You have a several issues:

    1. Replace NSDocumentationDirectory with NSDocumentDirectory.
    2. You are building your paths incorrectly. This:

      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
      NSString *docPath = [paths objectAtIndex:0];
      NSString *filePath = [docPath stringByAppendingFormat:@"%@.png",[self getdateAndTime]];
      

      should be:

      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      NSString *docPath = [paths objectAtIndex:0];
      NSString *filename = [NSString stringWithFormat:@"%.png", [self getdataAndTime]];
      NSString *filePath = [docPath stringByAppendingPathComponent:filename];
      

      Note the use of stringByAppendingPathComponent:. This is important. Without it you end up with:

      .../sandboxpath/Documentsfilename.png

      instead of:

      .../sandboxpath/Documents/filename.png

      Make the same fix in both methods.

    3. You are saving the fullpath to your Photo object. Never save absolute paths. They change over time. Only save the filename relative to Documents. So change:

      photo.photoName = filePath;
      

      to:

      photo.photoName = filename;
      

      When you read the value back in the future, append it to the Document path.

    4. Your error checking should be:

      if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
          NSLog(@"The file exists");
      } else {
          NSLog(@"errorIS %@", error);
      }