What can cause a block not to save an Objective-C reference object in ARC?

I received a crash message saying the following:

*** Application terminated due to an uncaught exception "NSInvalidArgumentException", reason: '- [__ NSMallocBlock__ CGImage]: unrecognized selector sent to instance 0x1fb17f90'

This usually happens when the object has been freed, and another object now lives at the same address as the freed object.

Here is my code (the only place in my application where Im calls the CGImage method):

 @implementation UIImageView (MyApp) - (void) setImageWithObject:(id)object { NSURLRequest *imageRequest = [NSURLRequest requestWithURL:[object URL]]; __typeof__(self) __weak weakSelf = self; [self setImageWithURLRequest:imageRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ CGImageRef imageRef = [image CGImage]; CGRect rect = CGRectMake(0.f, 0.f, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); CGContextRef bitmapContext = CGBitmapContextCreate(NULL, (size_t)roundf(CGRectGetWidth(rect)), (size_t)roundf(CGRectGetHeight(rect)), CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), CGImageGetColorSpace(imageRef), CGImageGetBitmapInfo(imageRef)); UIImage *decompressedImage = image; if (bitmapContext) { CGContextDrawImage(bitmapContext, rect, imageRef); CGImageRef decompressedImageRef = CGBitmapContextCreateImage(bitmapContext); decompressedImage = [UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation]; CGImageRelease(decompressedImageRef); CGContextRelease(bitmapContext); } dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.image = decompressedImage; }); }); } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { NSLog(@"%@", error); }]; } @end 

I suggested that the image object should be automatically saved by the block (Im using ARC), so the image object cannot be freed before the code using it is executed in the default priority queue. Failure apparently means that it was not saved.

Am I mistaken in my assumption or am I missing something else?

+4
source share
2 answers

Doesn't this look like behavior like on UIColor and CGColorRef under ARC? As described here: http://blog.bignerdranch.com/296-arc-gotcha-unexpectedly-short-lifetimes/

So where do you have:

 CGImageRef imageRef = [image CGImage]; 

I think you need to explicitly save it inside the block, and then release it explicitly so that ARC does not release the ref image.

So:

 CGImageRef imageRef = CGImageRetain([image CGImage]); ... CGImageRelease(imageRef); 
+2
source

There may be problems in your unit. Someone calls a block; it is possible that the caller has already passed the freed object. I would do NSLog (@ "% @", image) in the first line of the block, and also look at the call code.

0
source

All Articles