在 64 位系统上,UIButtons 出现在它们位于顶部的视图下方
UIButtons appear below the view that they are placed on top of when on a 64 bit system
背景
我有一个视图层次结构:
...在 UI 预览中看起来像这样:
每个按钮由一个图标("image" 属性)和一个背景图像("background" 属性)组成。背景图像基本上是一个可调整大小的斜角框架,结合底层 UIImageView (ButtonPanel) 为按钮提供最终外观。
然后我在自定义 segue 中有一段代码(通向这个控制器),它在控制器视图层次结构中的索引 0 处插入一个屏幕大小的视图:
background.tag = NSIntegerMax;
[[self.destinationViewController view] insertSubview:background atIndex:0];
现在它运行良好并且没有任何问题......直到我更改架构以包含 arm64(64 位)和 运行 它在 64 位设备上。
问题
当运行 应用程序在 64 位系统上时,会发生以下情况:
- 只有中间按钮的图形可见。
- 其余按钮看起来好像它们将被隐藏或放置在 ButtonPanel 下方,但实际上它们不是(已在调试器中验证)。相反,图形呈现在 ButtonPanel 下方(通过稍微垂直偏移 ButtonPanel 进行验证)。
- 如果我移动中间的按钮使 x < 64 点,那么它的图形也会消失(如果我将它向右移动并且它的右边缘距离屏幕右边缘小于 64 点,则会发生相应的事情) .
- 如果我删除 insertSubview:atIndex: 调用,那么一切都会按预期进行。
以下是说明问题的一些图片:
(只有中间按钮可见)
(同上但 ButtonPanel 垂直偏移 -19 点)
更多信息
已采取以下步骤来解决错误的根源:
- 我已确保所有参与的视图都有 tag = 0;
- 与按钮相关的所有 IBOutlets 已被暂时删除;
- 所有其他不需要重现此错误的视图已被暂时删除;
- 将 insertSubview:atIndex 替换为 insertSubview:belowSubview 或 addSubview: 没有帮助;
其他可能相关的详细信息:
- 该项目彻底使用了自动调整大小蒙版(没有自动布局,也没有通用故事板);
- 部署目标是“6.0”;
- 我已按照 https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html
中的 Apple 指南将项目转换为 64 位
- 我未能在新项目中重现此错误,因此我目前无法提供任何项目文件来查看。
更新 (2015-03-16)
我现在找到了问题的根源。引用代码中的 "background" 变量实际上是一个 UIImageView,其图像 属性 是使用呈现的屏幕截图设置的。使用以下方法呈现屏幕截图:
- (UIImage*) createImageOfView:(UIView*)view withSize:(CGSize)size {
UIGraphicsBeginImageContextWithOptions(size, [view isOpaque], view.window.screen.scale);
CGContextRef const context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage* const image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
我已经确定整个问题与在此方法中调用 UIGraphicsBeginImageContextWithOptions 有关。 但它只会发生如果包含图像的 UIImageView 被插入到视图层次结构中(即简单地渲染屏幕截图不会导致问题)。
我现在尝试从资产目录分配图像,但出现了同样的问题。因此,只有当 UIImageView 的图像 属性 为 nil 时,一切都按预期工作;将图像 属性 设置为任何有效图像都会引入问题。
现在已经解决了!总共10个小时后...
不管怎样,事情是这样的。
插入的背景视图在被插入到问题中提到的视图层次结构之前确实参与了自定义转场动画。这个动画是 "horizontal flip over"。但是,我忘记重置用于此转换的转换。因此背景视图的有效宽度基本上为零(2.84217e-14)。将零宽度的视图插入视图层次结构显然会导致 64 位架构出现奇怪的行为。
最初我试图强制更改框架,但当框架没有响应时,这让我想到了过渡动画。因此,解决整个问题的方法是在最终的动画完成块中添加以下代码行:
fromView.layer.transform = CATransform3DIdentity;
toView.layer.transform = CATransform3DIdentity;
... 其中 fromView 是 "background" 上面的视图。
背景
我有一个视图层次结构:
...在 UI 预览中看起来像这样:
每个按钮由一个图标("image" 属性)和一个背景图像("background" 属性)组成。背景图像基本上是一个可调整大小的斜角框架,结合底层 UIImageView (ButtonPanel) 为按钮提供最终外观。
然后我在自定义 segue 中有一段代码(通向这个控制器),它在控制器视图层次结构中的索引 0 处插入一个屏幕大小的视图:
background.tag = NSIntegerMax;
[[self.destinationViewController view] insertSubview:background atIndex:0];
现在它运行良好并且没有任何问题......直到我更改架构以包含 arm64(64 位)和 运行 它在 64 位设备上。
问题
当运行 应用程序在 64 位系统上时,会发生以下情况:
- 只有中间按钮的图形可见。
- 其余按钮看起来好像它们将被隐藏或放置在 ButtonPanel 下方,但实际上它们不是(已在调试器中验证)。相反,图形呈现在 ButtonPanel 下方(通过稍微垂直偏移 ButtonPanel 进行验证)。
- 如果我移动中间的按钮使 x < 64 点,那么它的图形也会消失(如果我将它向右移动并且它的右边缘距离屏幕右边缘小于 64 点,则会发生相应的事情) .
- 如果我删除 insertSubview:atIndex: 调用,那么一切都会按预期进行。
以下是说明问题的一些图片:
(只有中间按钮可见)
(同上但 ButtonPanel 垂直偏移 -19 点)
更多信息
已采取以下步骤来解决错误的根源:
- 我已确保所有参与的视图都有 tag = 0;
- 与按钮相关的所有 IBOutlets 已被暂时删除;
- 所有其他不需要重现此错误的视图已被暂时删除;
- 将 insertSubview:atIndex 替换为 insertSubview:belowSubview 或 addSubview: 没有帮助;
其他可能相关的详细信息:
- 该项目彻底使用了自动调整大小蒙版(没有自动布局,也没有通用故事板);
- 部署目标是“6.0”;
- 我已按照 https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html 中的 Apple 指南将项目转换为 64 位
- 我未能在新项目中重现此错误,因此我目前无法提供任何项目文件来查看。
更新 (2015-03-16)
我现在找到了问题的根源。引用代码中的 "background" 变量实际上是一个 UIImageView,其图像 属性 是使用呈现的屏幕截图设置的。使用以下方法呈现屏幕截图:
- (UIImage*) createImageOfView:(UIView*)view withSize:(CGSize)size {
UIGraphicsBeginImageContextWithOptions(size, [view isOpaque], view.window.screen.scale);
CGContextRef const context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage* const image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
我已经确定整个问题与在此方法中调用 UIGraphicsBeginImageContextWithOptions 有关。 但它只会发生如果包含图像的 UIImageView 被插入到视图层次结构中(即简单地渲染屏幕截图不会导致问题)。
我现在尝试从资产目录分配图像,但出现了同样的问题。因此,只有当 UIImageView 的图像 属性 为 nil 时,一切都按预期工作;将图像 属性 设置为任何有效图像都会引入问题。
现在已经解决了!总共10个小时后... 不管怎样,事情是这样的。
插入的背景视图在被插入到问题中提到的视图层次结构之前确实参与了自定义转场动画。这个动画是 "horizontal flip over"。但是,我忘记重置用于此转换的转换。因此背景视图的有效宽度基本上为零(2.84217e-14)。将零宽度的视图插入视图层次结构显然会导致 64 位架构出现奇怪的行为。
最初我试图强制更改框架,但当框架没有响应时,这让我想到了过渡动画。因此,解决整个问题的方法是在最终的动画完成块中添加以下代码行:
fromView.layer.transform = CATransform3DIdentity;
toView.layer.transform = CATransform3DIdentity;
... 其中 fromView 是 "background" 上面的视图。