Прежде всего, вы не должны звонить drawRect:
самостоятельно, UIKit сделает это за вас.Вы должны позвонить setNeedsDisplay
.Во-вторых, UIKit не является поточно-ориентированным, поэтому вызов любых операций рисования UIKit в любом потоке, кроме основного, может привести к сбою приложения, как вы уже видели.
Однако CoreGraphics является потоко-безопасным, если вы создаетеконтекст, чтобы нарисовать в себе, а затем использовать только вызовы CoreGraphics.Итак, что вы можете сделать, это сделать ваше трудоемкое рисование в фоновом потоке с CoreGraphics, где вы рисуете в контексте изображения и сохраняете изображение в переменной экземпляра.Затем вызовите setNeedsDisplay
в главном потоке и просто отобразите визуализированное изображение в вашем методе drawRect:
.
Так в псевдокоде (версия Core Graphics):
- (void)redraw
{
[self performSelectorInBackground:@selector(redrawInBackground) withObject:nil];
}
- (void)redrawInBackground
{
CGImageRef image;
CGContextRef context;
context = CGBitmapContextCreate(..., self.bounds.size.width, self.bounds.size.height, ...);
// Do the drawing here
image = CGBitmapContextCreateImage(context);
// This must be an atomic property.
self.renderedImage:[UIImage imageWithCGImage:image]];
CGContextRelease(context);
CGRelease(image);
[self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
}
- (void)drawRect:(CGRect)rect
{
[self.renderedImage drawAtPoint:CGPointMake(0,0)];
}
UIKitверсия будет:
- (void)redrawInBackground
{
UIGraphicsBeginImageContext(self.bounds.size);
// Do the drawing here.
self.renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
}