Во-первых, вы не должны сами звонить 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];
}
person
DarkDust
schedule
18.02.2012