通过阅读Apple的文档我可以看出,UI更新只能在主线程上运行。
我的应用程序在屏幕的上半部分进行了一些渲染,并在下半部分有一个表格视图。如果用户在上半部分重新绘制时滚动表格,则表格会锁定半秒钟左右。有什么方法可以改善这种情况吗?
答案 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,否则你将开始丢帧。