iPhone iPad 上的应用程序:drawViewHierarchyInRect 导致故障

iPhone app on iPad: drawViewHierarchyInRect causes glitch

运行 iPad (iOS 8) 上的 iPhone 应用程序,使用 drawViewHierarchyInRect 拍摄快照并在两个视图控制器之间制作自定义动画。它在 iPhone 上运行良好,但是当应用程序在 iPad 上(不是通用应用程序,仅 iPhone)时,您可以在动画开始时看到一个错误快照的简短一瞥。基本上它似乎拍摄了整个 iPad 屏幕的快照,包括黑边,而不仅仅是模拟的 iPhone 屏幕。该应用程序还隐藏了状态栏,但您可以在简短的一瞥中看到状态栏,这意味着它可能是 iOS 中的某种错误,因为 iPad 始终显示 iPhone 的状态栏屏幕顶部的应用程序。

这是截图代码;

UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:update];
UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

顺带一提,在 Apple TV 上使用 Airplay 播放应用程序时也会发生闪退。

事实证明,在这种情况下,drawViewHierarchyInRect 似乎以某种方式短暂地渲染到屏幕上...用 CALayer 的 renderInContext 替换它可以消除故障,但不幸的是,我的 iPhone 性能较差,所以我添加了一个检查确保 iPad 模拟是唯一需要执行此操作的模拟(幸运的是它在 iPad 上足够快)

UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
if( [self iPadRunningiPhoneSize] )
{
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
}
else
{
    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:update];
}
UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

以及检查 iPhone 应用在 iPad 上 'simulated' 的情况的功能,以防该应用后来通用

- (BOOL)iPadRunningiPhoneSize
{
    int name[] = {CTL_HW,HW_MACHINE};
    size_t size = 100;
    sysctl(name, 2, NULL, &size, NULL, 0); // getting size of answer
    char *hw_machine = malloc(size);

    sysctl(name, 2, hw_machine, &size, NULL, 0);
    NSString *hardware = [NSString stringWithUTF8String:hw_machine];
    free(hw_machine);

    int greaterBound = MAX( [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height );

    return [hardware rangeOfString: @"iPad"].location != NSNotFound && greaterBound == 480;
}

当使用 iPad 播放到 Apple TV 时,故障已修复,但当然检查 iPad 模拟 iPhone 应用程序意味着 iPhone使用 Airplay 时仍然会在电视上出现故障,但这不是这个应用程序的大问题!

用下面的代码替换你的代码,

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();