Search code examples
iospropertiescrashios-simulatorcalayer

App crashes on iPad but not in iPad Simulator


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;
}

Crash Log

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

Solution

  • 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.