我有一些繁重的UI绘制操作,因此我将其传递给了后台线程。我报告的崩溃中大约有100%发生在此操作中。当图形在主线程上运行时,就没有这种问题了,代码只是被取消了。
有在后台绘制的风险吗?
(我正在填充UIScrollView内容,可能是那里的问题吗?)
最佳答案
首先,您不应该自己调用drawRect:
,UIKit会为您执行此操作。您应该调用setNeedsDisplay
。其次,UIKit不是线程安全的,因此,如您所见,在主线程以外的任何线程上调用任何UIKit绘图操作都可能使您的应用程序崩溃。
但是,如果您创建自己绘制的上下文然后仅使用CoreGraphics调用,则CoreGraphics是线程安全的。因此,您可以做的是使用CoreGraphics在后台线程中进行耗时的绘制,在该线程中您可以绘制图像上下文并将图像存储在实例变量中。然后在主线程上调用setNeedsDisplay
,并简单地在drawRect:
方法中显示渲染的图像。
因此,在伪代码(核心图形版本)中:
- (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];
}
关于iphone - 可以在后台线程上调用dawRect:导致崩溃吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9344697/