Somewhere along the line, my app started crashing on the iPad though it still works great in the Simulator. I'm using XCode 4.3.1, and deploying on iOS 5.1.
The relevant code is below. It crashes when executing ImageLayer's drawInContext: method.
ImageLayer.h:
#import <QuartzCore/QuartzCore.h>
@interface ImageLayer : CALayer {}
@property (nonatomic, retain) NSString *path;
@end
ImageLayer.m:
#import "ImageLayer.h"
@implementation ImageLayer
@synthesize path;
- (void)drawInContext:(CGContextRef)ctx
{
[super drawInContext:ctx];
CGImageRef img = [UIImage imageWithContentsOfFile:path].CGImage;
NSLog(@"path = %@", path);
if (img) {
CGRect rect = CGContextGetClipBoundingBox(ctx);
CGContextTranslateCTM(ctx, 0.0, rect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
rect = CGContextGetClipBoundingBox(ctx);
CGContextDrawImage(ctx, rect, img); // Crashes here!
CGContextScaleCTM(ctx, 1.0, -1.0);
}
}
@end
LayeredView.h:
#import <UIKit/UIKit.h>
@interface LayeredView : UIView {}
@end
LayeredView.m:
#import "LayeredView.h"
#import "ImageLayer.h"
@implementation LayeredView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSString *path = [[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: @"Letter A"] stringByAppendingPathComponent:@"bg.png"];
ImageLayer *l = [ImageLayer layer];
l.path = path;
l.frame = CGRectMake(0, -27, 1024, 795);
[self.layer addSublayer:l];
[l setNeedsDisplay];
}
return self;
}
Incident Identifier: F0104517-289E-4B50-BBD0-5E9E0B19BAE8
CrashReporter Key: dc4048f7e9778dfac3941d3352d4edac4a35bd47
Hardware Model: iPad2,1
Process: ABC [4843]
Path: /var/mobile/Applications/88FE4107-4433-4A36-A511-0B9619B256EB/ABC.app/ABC
Identifier: ABC
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2012-03-16 14:38:30.326 -0700
OS Version: iPhone OS 5.1 (9B176)
Report Version: 104
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x371a132c 0x37190000 + 70444
1 libsystem_c.dylib 0x33307208 0x332ba000 + 315912
2 libsystem_c.dylib 0x33300298 0x332ba000 + 287384
3 GraphicsServices 0x333d987c 0x333d5000 + 18556
4 GraphicsServices 0x333da2bc 0x333d5000 + 21180
5 UIKit 0x35b50c5a 0x35b1f000 + 203866
6 ABC 0x000e045c 0xdf000 + 5212
7 ABC 0x000e0400 0xdf000 + 5120
Found it. By changing this line
CGImageRef img = [UIImage imageWithContentsOfFile:path].CGImage;
to
UIImage *image = [UIImage imageWithContentsOfFile:path];
CGImageRef img = image.CGImage;
everything works fine. My guess is that ARC hangs on to just the CGImageRef, and disposes of the image, unless a variable is allocated for it.