ios - drawViewHierarchyInRect 与 renderInContext 的预期性能是什么

标签 ios objective-c uiimage screenshot

在浏览了关于 SO 的所有相关问题后,我了解到 drawViewHierarchyInRect 应该比 renderInContext 快得多,但这不是我所看到的。

这是我的带有时间分析的快照功能:

- (UIImage *)screenshot
{
    UIScreen *mainScreen = [UIScreen mainScreen];
    CGSize imageSize = mainScreen.bounds.size;
    if (&UIGraphicsBeginImageContextWithOptions != NULL) {
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 1);
    } else {
        UIGraphicsBeginImageContext(imageSize);
    }

    CGContextRef context = UIGraphicsGetCurrentContext();

    NSArray *windows = [[UIApplication sharedApplication] windows];
    for (UIWindow *window in windows) {
        if (![window respondsToSelector:@selector(screen)] || window.screen == mainScreen) {
            NSDate *methodStart = [NSDate date];

//            [window.layer renderInContext:context];
            [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:NO];

            NSDate *methodFinish = [NSDate date];
            NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
            NSLog(@"executionTime = %f", executionTime);
        }
    }

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return image;
}

测试是在装有 IOS 9.0 的 iPad Air 上完成的
作为一个测试应用程序,我正在使用 UIKitCatalog 应用程序 https://developer.apple.com/library/ios/samplecode/UICatalog/Introduction/Intro.html

该应用程序显示 2 个窗口:
<UIWindow: 0x134e4d8f0; frame = (0 0; 768 1024); gestureRecognizers = <NSArray: 0x134e27740>; layer = <UIWindowLayer: 0x134e4d130>>,
<UITextEffectsWindow: 0x134e6a3a0; frame = (0 0; 768 1024); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x134e6aba0>>

使用 drawViewHierarchyInRect 会导致 0.078s 任意 两个窗口中的
renderInContext 结果 0.045s 在主窗口上,在 UITextEffectsWindow 上的时间更短(0.000028 秒)。
  • 为什么drawViewHierarchyInRect比renderInContext慢,不应该更快
  • 两者(78ms,45ms)对于以任何不错的帧速率录制屏幕视频都是 Not Acceptable 。似乎有些地方很不对劲,应该快得多。
  • [window.layer renderInContext...] 导致屏幕截图困惑且不准确,我尝试过 [window.layer.presentationLayer renderInContext...],但这会导致应用程序崩溃,我找不到原因。

  • 我将不胜感激,我要做的就是以尽可能高的帧速率录制屏幕视频,到目前为止,我得到的结果没有意义,或者我可能做错了什么。

    谢谢

    最佳答案

    您询问:

    1. Why is drawViewHierarchyInRect slower than renderInContext, isn't it supposed to be faster?


    这完全取决于您要捕获的内容。例如,用一堆简单的 UIView 捕获 View subview ,我看不出有什么明显的区别。当使用复杂的 UIImageView 捕获 View 时(例如非常高分辨率的图像),我发现 drawViewHierarchyInRect在极端情况下可以大约快 10 倍。我发现后者的性能差异与 Apple 在 Implementing Engaging UI in iOS 中声称的相当。他们的示例包括一堆 ImageView 。

    我从那些诊断中推断出 drawViewHierarchyInRect已针对 UIImageView 的屏幕快照进行了优化对象。因此,虽然它可能针对特定场景进行了高度优化,但我并不完全惊讶于可能存在不打算产生相同结果的场景。

    1. Both (78ms, 45ms) are unacceptable for recording video of the screen with any decent frame rate. Seems like something is very wrong, it should be much faster.


    这些不是为视频捕获而设计的,所以我不确定你所说的“事情很不对劲”是什么意思。为什么说“它应该更快”?

    1. [window.layer renderInContext...] results in screenshots which are messy and inaccurate ...


    您应该编辑您的问题以包括屏幕快照以向我们展示您的意思。

    ... I've tried [window.layer.presentationLayer renderInContext...], yet this results in application crashes and I can't find the reason.


    presentationLayer方法是获取当前演示状态的副本(通常用于查询中间动画),但它不是您通常与之交互的层。

    关于ios - drawViewHierarchyInRect 与 renderInContext 的预期性能是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33592307/

    相关文章:

    ios - 如何在选择每个图标时为每个图标设置不同的 UITabBar.tintColor ?

    ios - objective-c dateFromString 在特定日期返回 nil

    ios - 计算 UITextView 所需的大小

    objective-c - 具有底部反射的 UIImage

    iOS 调整大小并裁剪非方形图像 - 高质量

    ios - XCode4代码需要签名3次吗?

    objective-c - Xcode 构建但不在设备上运行

    ios - 如何在 Objective-C 中以编程方式检查协议(protocol)是否包含某些方法?

    objective-c - NSOperation 子类 isCancelled isFinished isConcurrent

    ios - 如何调整 UIImage 的大小以减小上传图片的大小