0

So I'm building an app that the user takes pictures of themselves, it saves them to the camera roll, and I'm saving references to the asset URLs to display them in the app. At first this model seemed to work fine, but as I took more and more pictures it started receiving memory warnings and eventually crashed. Is there a better way to approach this?

This is how I load up the saved photos at the launch of the app (which freezes the app for up to 10 seconds depending on how many are being loaded):

- (void) loadPhotosArray
{
    _photos = [[NSMutableArray alloc] init];

    NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey: @"savedImages"];
    if (data)
    {
        NSArray* storedUrls = [[NSArray alloc] initWithArray: [NSKeyedUnarchiver unarchiveObjectWithData: data]];

        // reverse array
        NSArray* urls = [[storedUrls reverseObjectEnumerator] allObjects];

        for (NSURL* assetUrl in urls)
        {
            // Block to handle image handling success
            ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
            {
                ALAssetRepresentation *rep = [myasset defaultRepresentation];
                CGImageRef iref = [rep fullResolutionImage];
                if (iref) {
                    UIImage* tempImage = [UIImage imageWithCGImage:iref];
                    UIImage* image = [[UIImage alloc] initWithCGImage: tempImage.CGImage scale: 1.0 orientation: UIImageOrientationRight];

                    // Set image in imageView
                    [_photos addObject: image];
                    [[NSNotificationCenter defaultCenter] postNotificationName: @"PhotosChanged" object: self];
                }
            };

            // Handles failure of getting image
            ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
            {
                NSLog(@"Can't get image - %@",[myerror localizedDescription]);
            };

            // Load image then call appropriate block
            ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
            [assetslibrary assetForURL: assetUrl
                           resultBlock: resultblock
                          failureBlock: failureblock];
        }
    }
    else
    {
        NSLog(@"Photo storage is empty");
    }
}

And saving photos:

- (void) addImageToPhotos: (UIImage*)image
{
    // Store image at front of array
    NSMutableArray* temp = [[NSMutableArray alloc] initWithObjects: image, nil];

    // load rest of images onto temp array
    for (UIImage* image in _photos)
    {
        [temp addObject: image];
    }

    _photos = nil;
    _photos = [[NSMutableArray alloc] initWithArray: temp];

//    [self.photos addObject: image];
    [[NSNotificationCenter defaultCenter] postNotificationName: @"PhotosChanged" object: self.photos];

    // save to cache
    ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
    [library saveImage: image toAlbum: @kAlbumeName withCompletionBlock:^(NSError *error) {
        if (error)
        {
            NSLog(@"Error saving");
        }

    }];

}
Chris
  • 7,270
  • 19
  • 66
  • 110

1 Answers1

2

I think have 2 methods to optimize this problem.

  1. U should just save image name string instead of saving UIImage object, then when need to display the image, use pagination to display image according to saved image name string.

  2. U should use multi-thread to deal with this long time task, recommend u to use gcd to load image name string.

timothy lau
  • 386
  • 2
  • 2