Search code examples
iosdelegatesuiimagensoperationqueuensoperation

App crashing after while calling delegate


I've a NSOperation class that generated small and large image from a PHASSET. It's something like this:

#import "MultipleImageOperation.h"

@implementation MultipleImageOperation

@synthesize asset = _asset;
@synthesize tag = _tag;
@synthesize isLogo = _isLogo;
@synthesize delegate = _delegate;

-(id)initWithAsset:(PHAsset*) asset andTag:(NSUInteger)theTag andDelegate:(id<MultipleImageOperationDelegate>)theDelegate {
    if(self = [super init]) {
        _asset = asset;
        _tag = theTag;
        _delegate = theDelegate;
    }
    return self;
}

- (void)main {
    @autoreleasepool {
        __block UIImage *smallImage, *largeImage;
        if (self.isCancelled == NO){
            PHImageRequestOptions *requestOptions =  [[PHImageRequestOptions alloc] init];
            requestOptions.resizeMode   = PHImageRequestOptionsResizeModeExact;
            requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
            requestOptions.synchronous = true;
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsDirectory = [paths objectAtIndex:0];
            PHImageManager *manager = [PHImageManager defaultManager];

            [manager requestImageForAsset:_asset
                     targetSize:!_isLogo? LARGE_IMAGE_SIZE : COMPANY_LOGO_LARGE_SIZE
                     contentMode:PHImageContentModeAspectFit
                     options:requestOptions
                     resultHandler:^void(UIImage *image, NSDictionary *info) {

                         NSData *imageData = UIImagePNGRepresentation(image);
                         NSString *filename = [NSString stringWithFormat:@"/img_%f.png", [[Utils getCurrentDate] timeIntervalSince1970]];
                         NSString *tempPath = [documentsDirectory stringByAppendingString:filename];
                         [imageData writeToFile:tempPath atomically:YES];
                         largeImage = image;
            }];
            [manager requestImageForAsset:_asset
                     targetSize:!_isLogo? SMALL_IMAGE_SIZE : COMPANY_LOGO_SMALL_SIZE
                     contentMode:PHImageContentModeAspectFit
                     options:requestOptions
                     resultHandler:^void(UIImage *image, NSDictionary *info) {

                         smallImage = image;
            }];
            if ([self.delegate respondsToSelector:@selector(multipleImageProcessingOperationCompletedForTag:withSmallImage:andLargeImage:)]) {
                    [self.delegate multipleImageProcessingOperationCompletedForTag:_tag withSmallImage:smallImage andLargeImage:largeImage];
            }

        }
    }
}


@end

Delegate method is as follow:

- (void) multipleImageProcessingOperationCompletedForTag:(NSUInteger)tag withSmallImage:(UIImage *)smallImage andLargeImage:(UIImage*)largeImage {
    Media *tempMedia;
    tempMedia = [self.imagesList objectAtIndex:tag];
    tempMedia.smallImage = smallImage;
    tempMedia.mediaContent = largeImage;
    tempMedia.mediaContentSize = [NSNumber numberWithDouble:([Utils convertToNSDataFromUIImage:largeImage].length/BYTES_IN_GB)];

    [self updateImagesList:tempMedia];
    photoOperations--;
    if ( photoOperations == 0 ) {
        if ([self.delegate respondsToSelector:@selector(updateDisplay)]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.delegate updateDisplay];
            });
        }
    }
}

018-11-05 16:20:09.633[722:137251] *** -[UIImage retain]: message sent to deallocated instance 0x198dbe20

small image is always nil! I am stuck with this!


Solution

  • I don't know anything about your image generation libraries, but it looks like the method that you use to create the small image with is asynchronous. That means that when you are calling your delegate method the small image method has likely not finished it's task. I would do:

    [manager requestImageForAsset:_asset
        targetSize:!_isLogo? SMALL_IMAGE_SIZE : COMPANY_LOGO_SMALL_SIZE
        contentMode:PHImageContentModeAspectFit
        options:requestOptions
        resultHandler:^void(UIImage *image, NSDictionary *info) {
            smallImage = image;
            if ([self.delegate respondsToSelector:@selector(multipleImageProcessingOperationCompletedForTag:withSmallImage:andLargeImage:)]) 
            {
                [self.delegate multipleImageProcessingOperationCompletedForTag:_tag withSmallImage:smallImage andLargeImage:largeImage];
            }
    }];
    

    But you are also going to have to make sure the large image method is done as well (in case it is asynchronous as well).