可以调用dawRect:在后台线程导致崩溃?

Ger*_*eri 0 iphone crash multithreading drawrect

我有一些沉重的UI绘图操作,所以我把它传递给后台线程.在此次手术中,我报告的大约100%的坠机事故发生了.当绘图在主线程上运行时,没有这样的问题,代码只是没有用.

是否有在后台绘图的风险?

(我正在填充UIScrollView内容,可能是那里的问题?)

Dar*_*ust 7

首先,你不应该给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)];
}
Run Code Online (Sandbox Code Playgroud)

UIKit版本将是:

- (void)redrawInBackground
{
    UIGraphicsBeginImageContext(self.bounds.size);

    // Do the drawing here.

    self.renderedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
}
Run Code Online (Sandbox Code Playgroud)