后台线程上的drawViewHierarchyInRect

Fit*_*rst 8 multithreading screenshot uiview ios

我正在尝试在后台线程上进行一些"屏幕外渲染",以更新我正在创建的类似设计器的应用程序的预览.

我已经使用renderInContextNSOperationQueue派生的队列来实现这一点,但请注意它很慢.

所以,我已经开始使用drawViewHierarchyInRect哪个效果很好而且速度更快.但是,我注意到当这个方法以b/g运行时,我的UI完全阻塞.

如果我在主线程上这样做...

    UIView *preview = [[UIView alloc]initWithFrame:CGRectMake(0, 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();
Run Code Online (Sandbox Code Playgroud)

......一切正常.

但是,如果我(比如说)派遣这个......

if (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW) == 0) 
{
    dispatch_async(renderQueue, ^{
        // capture
        UIView *preview = [[UIView alloc]initWithFrame:CGRectMake(0, 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();
}
        dispatch_semaphore_signal(semaphore);
    });
Run Code Online (Sandbox Code Playgroud)

...我的用户界面在执行完毕后冻结了.

'ok'返回YES,所以一切似乎都有效.

如果我将afterUpdates设置为NO,则'ok'为NO(失败),但UI仍然响应.

使用drawViewHierarchyInRect除主线程以外的任何东西都有任何限制吗?

小智 2

UIKit 对象只能在主线程上操作。Apple的UIKit文档提到了这句话

\n\n
\n

大多数情况下,仅在 app\xe2\x80\x99s 主线程中使用 UIKit 类。对于从 UIResponder 派生的类或涉及以任何方式操作您的应用程序\xe2\x80\x99s 用户界面的类来说尤其如此。

\n
\n