iPad 上的 iPhone 应用程序:drawViewHierarchyInRect 导致故障
Posted
技术标签:
【中文标题】iPad 上的 iPhone 应用程序:drawViewHierarchyInRect 导致故障【英文标题】:iPhone app on iPad: drawViewHierarchyInRect causes glitch 【发布时间】:2015-05-08 09:00:24 【问题描述】:在 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();
顺便说一句,使用 Airplay 在 Apple TV 上显示应用程序时也会出现闪烁。
【问题讨论】:
【参考方案1】:用下面的代码替换你的代码,
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
【讨论】:
是的,CMash。但我的意见是,无论设备如何,都只需添加这些行。因为这适用于 iPad n iPhone。所以不需要检查。 layer renderInContext 函数性能差很多,所以会导致延迟 是的,我读过一些相同的内容。这也向 Apple 报告。苹果只建议了上述解决方案。【参考方案2】:事实证明,在这种情况下,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();
以及检查在 iPad 上“模拟”iPhone 应用程序的情况的功能,以防应用程序以后通用
- (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 进行 Airplay 时,故障已得到修复,但当然,检查模拟 iPhone 应用程序的 iPad 意味着使用 Airplay 的 iPhone 仍会在电视上出现故障,但这并不是一个大问题应用!
【讨论】:
以上是关于iPad 上的 iPhone 应用程序:drawViewHierarchyInRect 导致故障的主要内容,如果未能解决你的问题,请参考以下文章
iPad 模拟器上的 Xcode 5 iPhone 应用程序
当 iPhone 家庭设置时,appstore 上的应用程序是不是支持 iPad?
Xcode 6.0.1 仅限 iPhone 的应用程序的行为类似于 iPad 上的普通 iPad 应用程序 - iOS 8