9

I am using PHImageManagers's requestImageDataForAsset to calculate memory size of particular photos in camera roll. It is working fine in my device but some users getting countinous crash after calculate memory size (found by analytics and crash report).

code and crash report

Please help.

Madhubalan K
  • 357
  • 5
  • 21

3 Answers3

2

On which iOS version it is crashing, seems working fine for me in iOS 8.3 , if you are exactly using the same process to fetch image meta data or memory size:-

--------------------------------------------------------------
-- get the UIImage instance from a PHAsset
--------------------------------------------------------------

- (UIImage*)grabImageFromAsset:(PHAsset *)asset
{
    __block UIImage *returnImage;
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    options.synchronous = YES;
    [[PHImageManager defaultManager] requestImageForAsset:asset
                                               targetSize:CGSizeMake(200, 200)
                                              contentMode:PHImageContentModeAspectFill
                                                  options:options
                                            resultHandler:
     ^(UIImage *result, NSDictionary *info) {
         returnImage = result;
     }];
    return returnImage;
}

--------------------------------------------------------------
-- get the metadata of the image from a PHAsset
--------------------------------------------------------------

- (NSDictionary *)grabImageDataFromAsset:(PHAsset *)asset
{
    __block NSMutableDictionary *imageAssetInfo = [NSMutableDictionary new];
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    options.synchronous = YES;
    [[PHImageManager defaultManager] requestImageDataForAsset:asset
                                                      options:options
                                                resultHandler:
     ^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
         if ([info[@"PHImageResultIsInCloudKey"] isEqual:@YES]) {
             // in the cloud
             NSLog(@"in the cloud (sync grabImageDataFromAsset)");
         }
         imageAssetInfo = [info mutableCopy];
         if (imageData) {
             imageAssetInfo[@"IMAGE_NSDATA"] = imageData;
         }
     }];
    return imageAssetInfo;
}

I am following this links for my photo kit operation:- phimagemanager and ios-8-photokit

Vizllx
  • 9,135
  • 1
  • 41
  • 79
  • OP is using Swift; that might make a difference here. – DarkDust May 15 '15 at 12:55
  • I know its in swift, but in this link 'https://github.com/vandadnp/iOS-8-Swift-Programming-Cookbook/blob/master/chapter-camera/Searching%20for%20and%20Retrieving%20Images%20and%20Videos/Searching%20for%20and%20Retrieving%20Images%20and%20Videos/ViewController.swift', they are using same script, and it works. – Vizllx May 18 '15 at 07:07
  • @Vizllx that link does not exists – Alvin Varghese Jun 09 '15 at 05:49
  • 1
    fixed link: https://github.com/vandadnp/iOS-8-Swift-Programming-Cookbook/blob/master/chapter-camera/Searching%20for%20and%20Retrieving%20Images%20and%20Videos/Searching%20for%20and%20Retrieving%20Images%20and%20Videos/ViewController.swift (previous didn't work just because ' symbol at end) – Akhrameev Nov 11 '16 at 11:47
2

I had an issue similar to this when users had their photos stored in iCloud using iCloud photo library. I was able to fix the issue by making the call asynchronous. It looks like this

let options = PHImageRequestOptions()
options.synchronous = false
options.networkAccessAllowed = true

Here is the whole function.

func getImageDataFromAsset(asset: PHAsset, completion: (data: NSData?) -> Void) {
    let manager = PHImageManager.defaultManager()
    let options = PHImageRequestOptions()
    options.networkAccessAllowed = true
    options.synchronous = false
    manager.requestImageDataForAsset(asset, options: options) { (result, string, orientation, info) -> Void in
        if let imageData = result {
            completion(data: imageData)
        } else {
            completion(data: nil)
        }
    }
}
Micah Wilson
  • 1,472
  • 12
  • 13
0

If you want load all photos that you have in Photos.app and you didn't want iCloud. You can do:

That example works with a collection view.

@interface GalleryViewModel ()

@property (strong, nonatomic) NSMutableArray<PHAsset *> *assets;
@property (strong, nonatomic) PHImageManager *imageManager;
@property (strong, nonatomic) PHImageRequestOptions *requestOptions;

@property (strong, nonatomic) NSMutableArray<UIImage *> *imagesList;

@end

@implementation GalleryViewModel

- (instancetype) initWithContext:(ITXAppContext *)context {
    self = [super initWithContext:context];
    if (self) {
        _assets = [[NSMutableArray alloc] init];
        _imageManager = [PHImageManager defaultManager];
        _requestOptions = [[PHImageRequestOptions alloc] init];
        _imagesList = [[NSMutableArray alloc] init];
    }
    return self;
}

#pragma mark - Public methods

// ==================================================================================
// Public methods

- (void) viewModelDidLoad {
    [self obtainAllPhotos];
}

#pragma mark - Private methods

// ==================================================================================
// Private methods

- (void) obtainAllPhotos {

    self.requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
    self.requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
    self.requestOptions.synchronous = YES;
    self.requestOptions.networkAccessAllowed = NO;

    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
    fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
    PHFetchResult<PHAsset *> *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];

    __weak GalleryViewModel *weakSelf = self;
    [result enumerateObjectsUsingBlock:^(PHAsset * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [weakSelf.assets addObject:obj];
        if (idx >= ([result count] - 1)) {
            [weakSelf.viewDelegate setupView];
        }
    }];
}

#pragma mark - Get data from object

// ==================================================================================
// Get data from object

- (NSInteger) sizeGallery {

    if (self.assets) {
        return [self.assets count];
    }
    return 0;
}

- (UIImage *) imagesFromList:(NSInteger) index {

    __block UIImage *imageBlock;

    [self.imageManager requestImageForAsset:[self.assets objectAtIndex:index] targetSize:CGSizeMake(200, 200) contentMode:PHImageContentModeAspectFit options:self.requestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        if (result) {
            imageBlock = result;
        }
    }];

    return imageBlock;
}

@end
jordiz
  • 279
  • 3
  • 8