如何同时执行两个UI更新?

时间:2011-08-01 19:31:18

标签: iphone ios multithreading xcode

通过阅读Apple的文档我可以看出,UI更新只能在主线程上运行。

我的应用程序在屏幕的上半部分进行了一些渲染,并在下半部分有一个表格视图。如果用户在上半部分重新绘制时滚动表格,则表格会锁定半秒钟左右。有什么方法可以改善这种情况吗?

2 个答案:

答案 0 :(得分:1)

如果绘制视图需要花费大量时间,我建议在更新时将其绘制到后台线程中的图像中,并让视图简单地绘制图像。这样可以防止主线程长时间阻塞。

以下代码显示如何从后台线程创建和绘制位图上下文。当您调用updateInBackground方法时,它将创建一个新的后台线程,创建并绘制到上下文中,然后使用该上下文创建一个图像。如果将其放在UIImageView的自定义子类中,则图像将自动绘制到屏幕上。

- (void)updateInBackground {
    [self performSelectorInBackground:@selector(_drawInBackground:) withObject:[NSValue valueWithCGRect:self.bounds]];
}
- (void)_drawInBackground:(NSValue *)boundsValue {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    CGRect bounds = [boundsValue CGRectValue];
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    if(!colorSpace) {
        [pool drain];
        return;
    }
    CGContextRef context = CGBitmapContextCreate(NULL,bounds.size.width, bounds.size.height, 8, bounds.size.width * 32, colorSpace, kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);
    if(!context) {
        [pool drain];
        return;
    }
    CGContextConcatCTM(context, CGAffineTransformMake(1,0,0,-1,0,bounds.size.height));

    // do drawing here

    CGImageRef image = CGBitmapContextCreateImage(context);
    [self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageWithCGImage:image] waitUntilDone:YES];
    CGImageRelease(image);
    CGContextRelease(context);
    [pool drain];
}

在后台线程中绘图时,不能使用UIKit对象和方法。必须使用Quartz functions完成所有绘图。如果你需要使用UIKit,后台线程可以调用主线程上的方法来完成绘图的那一部分:

[self performSelectorOnMainThread:@selector(drawInMainThread:) withObject:[NSValue valueWithPointer:context] waitUntilDone:YES];

- (void)drawInMainThread:(NSValue *)value {
    UIGraphicsPushContext((CGContextRef)[value pointerValue]);
    // do drawing using UIKit
    UIGraphicsPopContext();
}

答案 1 :(得分:0)

听起来上半部分的画面需要一段时间。你通过乐器运行它吗?

重要的是要记住,如果你想要一个平滑的60FPS滚动,你的渲染(以及主线程上的任何其他cpu)每个循环必须少于16 MS,否则你将开始丢帧。