在iOS的后台线程中绘图

问题描述:

我有一些非常复杂的绘图逻辑(它是从GIS数据绘制的地图视图)的视图。在主线程中执行此绘图会锁定UI并使应用程序无响应。我想将绘图移动到后台线程,例如NSOperation。在iOS的后台线程中绘图

这种结构的最佳方式是什么?

我目前正在绘制一个关闭内存CGContext,然后将其转换为一个CGImageRef,我发送到视图blit主线程上。不幸的是,这消耗了大量的内存,看起来GPU加速已经不再使用,因为它比较慢。有没有从后台线程直接绘制视图的方法?我知道UIKit不是多线程安全的,但在绘图时可能有某种方式来锁定视图?

我从来没有遇到这种情况在iPhone上,但在Mac上我有类似的问题一次。

  1. 使用CGLayer委托脱机上下文的绘图活动。
  2. 尝试为当前NSRunLoop添加计时器,并按照定时间隔执行图形命令。它应该是这个样子...

...

kRenderFPS 25.0 //This is Maximum value 

renderTimer = [[NSTimer timerWithTimeInterval:(1.0/(NSTimeInterval)kRenderFPS) target:viewobject selector:@selector(RenderUI:) userInfo:nil repeats:YES] retain]; 


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSDefaultRunLoopMode]; 


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSModalPanelRunLoopMode]; 


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSEventTrackingRunLoopMode]; 

//In view class 
-(void)RenderUI:(id)param 
{ 
    [self setNeedsDisplayInRect:[self bounds]]; 
} 

这应该做的伎俩。

还尝试对您的进程进行采样并检查谁在使用CPU。这将使UI响应速度非常快。

您提到的性能问题可能是由于其他原因。尝试cpu示例过程。它会让你了解谁在实际使用CPU。

+0

你的意思是CALayer? –

+1

编号CGLayer。 http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGLayer/Reference/reference.html – MacGeek

+0

所以我现在正在尝试这种方法,但即使我运行NSTimer并只运行50%的时间(以0.2s间隔运行,每个绘图周期最多0.1s),它似乎仍然忽略了所有UI事件。这有什么窍门吗? –

超越iOS 4.0,drawing is thread safe。您可能需要自己创建一个CGContext,但没有理由不能在后台线程上绘制。

也就是说,大多数UIKit操作都不是。如果你需要这样做,你可以随时准备后台线程,然后在需要时使用performOnMainThread。甚至还有waitUntilDone。这就是说,显然你应该使用NSOperationNSOperationQueue

+1

似乎有很多这方面的困惑,但这是正确的答案,因为iOS 4.0的UIKit绘图是线程安全的。这是官方公告:http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS4.html(搜索“线程”)。 –

+0

@Jon Tirsen,感谢你帮助证实了答案。 –