ios - 未优化与优化二进制文件中的奇怪 ARC 行为

标签 ios objective-c llvm

我有一个很难跟踪的错误,它只出现在我的应用程序的发布版本中,但不出现在调试版本中。构建之间的相关差异原来是 Debug 构建是在没有任何编译器优化的情况下编译的,而 Release 构建是使用 -O 编译的(该错误也可以在所有其他优化设置上重现) .这一切都在 LLVM 上。

在我的 View Controller 中,我有一个属性 self.basicInfoContainerView 定义为:

@property (weak, nonatomic) IBOutlet UIView *basicInfoContainerView;

然后我从一个 View 中删除了 subview ,并将其添加到另一个 View 中。

[self.basicInfoContainerView removeFromSuperview];
[self.infoTextView addSubview:self.basicInfoContainerView];

根据编译器优化级别,会发生不同的事情。

启用优化:一旦 View 从其父 View 中移除, View 就会被释放并且 self.basicInfoContainerView 被置零,因此不会作为 subview 添加到新观点。

关闭优化: subview 没有立即释放,而是作为 subview 成功添加到新 View 。

(当我将属性存储限定符更改为 strong 时, View 在两种情况下都存在,但即使这解决了问题,但这并不是我的问题。)

我希望有人能帮助我理解这里到底发生了什么。当编译器优化关闭时,为什么 weak 不立即释放我的 View (如果保留计数 == 0,则将指针归零)?

最佳答案

保留对对象的额外本地(和强)引用的未优化代码确实很常见。因此,您未优化的代码必须具有对此“basicInfoContainerView”的本地强引用。该引用通过该方法保留在范围内,并且可能在该方法返回之前不会被释放。

这实际上只是一种意外,它掩盖了您代码中的真正错误。事实上,一旦你执行了[self.basicInfoContainerView removeFromSuperview],你就不能指望你的 basicInfoContainerView 会存活下来,因为你没有任何对该 View 的任何显式强引用更多。

当然,解决这个问题的方法是创建对该 View 的显式强引用。那么你已经向编译器明确了你的意图,无论代码是否优化,你都应该得到你想要的结果:

UIView *containerView = self.basicInfoContainerView
// this local variable is that explicit strong reference you need

[containerView removeFromSuperview];
[self.infoTextView addSubview:containerView];

// the compiler can/will release this view when the local variable
// 'containerView' goes out of scope

希望对您有所帮助。

关于ios - 未优化与优化二进制文件中的奇怪 ARC 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14356330/

相关文章:

ios - 在 react-native 中使用 iOS 启动屏幕作为应用程序背景

FunctionPass 中的 LLVM LoopInfo 无法编译

c++ - 测试执行后缺少某些 GCDA 文件

ios - UICollectionView reloadData 在 iOS 7 中无法正常运行

ios - 如何使用 Xcode 11 构建/提交使用 iOS 14 API 构建的应用程序?

android - libgdx:请求 GPS 地理定位?

objective-c - 输出正在调用方法的类的名称的最佳方式是什么?

objective-c - 如何确定 Apple 方法是否异步?

c++ - 在 Windows 上构建 LLVM 时出错 - LNK1104

iphone - CoreData 的自定义部分数组