In order to replicate a crash I was having in my application, I had to create a sample with a slightly exaggerated repeat rate that might not be practical, but one that demo
This appears to be a regression in iOS 5.x: It happens on the 5.0 and 5.1 simulators and on a 5.1 device, but not on the 4.3 simulator or a 4.3.2 device.
It's also specifically the string drawing that seems to be broken — if all you do is string-drawing (avoiding the overhead of creating/destroying contexts), the crash happens nearly instantly:
-(void)threadFunc:(UIFont *)font {
@autoreleasepool {
NSString *string = @" ";
CGRect r = {{0,0},{50,50}};
UIGraphicsBeginImageContextWithOptions(r.size, YES, 0);
for(;;) {
@autoreleasepool {
[string drawAtPoint:r.origin withFont:font];
}
}
UIGraphicsEndImageContext();
}
}
-(void)startThreads
{
UIFont * font = [UIFont systemFontOfSize:12];
for (int i = 2; i--;)
{
[NSThread detachNewThreadSelector:@selector(threadFunc:) toTarget:self withObject:font];
}
}
EDIT: It is "nearly instant" only in multi-core environments (i.e. a dual-core device or the simulator, assuming a multi-core Mac). Otherwise, it takes on the order of 10-20 minutes to crash. I don't have a dual-core iOS 4.x device (the only possibility appears to be the iPad 2), but the single-core devices haven't crashed after over an hour.
I've raised a bug with Apple, and encourage you to do the same if it affects you.
An easy workaround for this is to replace NSString with NSAttributedString.
The crash test that @maq listed does not crash if modified like this:
-(void)threadFunc:(UIFont *)font {
@autoreleasepool {
NSString *string = @" ";
NSMutableAttributedString *test = [[NSMutableAttributedString alloc] initWithString:string];
CGRect r = {{0,0},{50,50}};
UIGraphicsBeginImageContextWithOptions(r.size, YES, 0);
for(;;) {
@autoreleasepool {
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:30.0f];
[test addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, test.length)];
[test drawAtPoint:r.origin];
}
}
UIGraphicsEndImageContext();
}
}
I don't believe UIKit is thread safe, and drawing from a background thread is very funky. It might work, it might not.
The doc for UIGraphicsBeginContext actually explicitly states that you should only call this from the main thread. Clearly, multithreading is completely off the table.