我正在尝试在后台线程上进行一些“屏幕外渲染”,以更新我正在创建的类似设计器的应用程序的预览.
我在NSOperationQueue派生的队列上使用了renderInContext来完成这个,但是注意它很慢.
所以,我已经开始使用drawViewHierarchyInRect,它工作得很好而且速度更快.但是,我注意到当这个方法以b / g运行时,我的UI完全阻塞.
如果我在主线程上执行此操作…
UIView *preview = [[UIView alloc]initWithFrame:CGRectMake(0,100,100)]; preview.backgroundColor = [UIColor redColor]; UIGraphicsBeginImageContextWithOptions(preview.bounds.size,NO,0.0); BOOL ok = [preview drawViewHierarchyInRect:preview.bounds afterScreenUpdates:YES]; UIImage *img = nil; if( ok ) { img = UIGraphicsGetImageFromCurrentImageContext(); } UIGraphicsEndImageContext();
……一切正常.
但是,如果我(说)发送这个……
if (dispatch_semaphore_wait(semaphore,DISPATCH_TIME_NOW) == 0) { dispatch_async(renderQueue,^{ // capture UIView *preview = [[UIView alloc]initWithFrame:CGRectMake(0,100)]; preview.backgroundColor = [UIColor redColor]; UIGraphicsBeginImageContextWithOptions(preview.bounds.size,0.0); BOOL ok = [preview drawViewHierarchyInRect:preview.bounds afterScreenUpdates:YES]; UIImage *img = nil; if( ok ) { img = UIGraphicsGetImageFromCurrentImageContext(); } UIGraphicsEndImageContext(); } dispatch_semaphore_signal(semaphore); });
…我的用户界面冻结,完全执行后.
‘ok’返回YES,所以一切似乎都有效.
如果我将afterUpdates设置为NO,则’ok’为NO(失败),但UI仍然是响应式的.
使用drawViewHierarchyInRect除主线程以外的任何东西都有任何限制吗?
解决方法
UIKit对象只应在主线程上进行操作. Apple的
UIKit documentation提到了这个说法
For the most part,use UIKit classes only from your app’s main thread. This is particularly true for classes derived from UIResponder or that involve manipulating your app’s user interface in any way.