【发布时间】:2012-02-18 22:21:14
【问题描述】:
我有一些繁重的 UI 绘图操作,所以我将它传递给后台线程。我报告的大约 100% 的崩溃发生在此操作期间。绘图在主线程上运行时没有这样的问题,代码只是未处理。
在后台绘图有什么风险吗?
(我正在填充 UIScrollView 内容,可能是那里的问题?)
【问题讨论】:
标签: iphone multithreading crash drawrect
我有一些繁重的 UI 绘图操作,所以我将它传递给后台线程。我报告的大约 100% 的崩溃发生在此操作期间。绘图在主线程上运行时没有这样的问题,代码只是未处理。
在后台绘图有什么风险吗?
(我正在填充 UIScrollView 内容,可能是那里的问题?)
【问题讨论】:
标签: iphone multithreading crash drawrect
首先,你不应该自己打电话给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];
}
【讨论】: