3

我刚刚将我的应用程序切换到了 ARC。由于 Xcode 提供的重构工具,转换取得了部分成功。一个不起作用的部分是一个奇怪的错误。

我使用了方法 swizzling (method_exchangeImplementations),所以它不会调用 UIView 的 initWithFrame,而是调用我的 myInitWithFrame 代码。重构过程在myInitWithFrame的方法声明处抛出了错误,所以我在方法声明之后添加了__属性__ ((objc_method_family(init)))。现在这一切都适用于 iOS 6.0 及更高版本,但在 iOS 5.0(我想支持的最低 iOS)上它不起作用。我得到一个 EXC_BAD_ACCESS(代码=1,地址=0X28)。每次运行都会出现完全相同的内存地址。

我有一个 UIWebView 调用它:

[[UIWebView alloc] initWithFrame:webViewFrame];

在 myInitWithFrame 进行初始化后,它返回 self,然后崩溃。在线程跟踪中,它说它在 [UIWebView 保留] 方法上的苹果代码中崩溃(该方法显示为灰色),如下所示。

Thread 1, Queue : com.apple.main-thread
#0  0x3515a7d2 in -[UIWebView retain] ()
#1  0x316ddef4 in objc_retain ()
#2  0x0011528c in -[UIView(style) myInitWithFrame:]

抱歉,线程跟踪的格式不是很好,我没有足够的代表来发布图像。

有什么理由为什么相同的代码适用于 iOS 6.0,但不适用于 iOS 5.0?

4

1 回答 1

5

这个问题解决起来非常复杂。这个问题只出现在 iOS 5 上,而不是 iOS 6 上,这是我第一个迹象表明这可能是苹果问题,或者是方法调配问题。经过大约一周的搜索,我达成了共识,我应该给 Apple 技术支持发送电子邮件,看看他们是否可以帮助我解决这个问题。

他们的回答是,这都是我们的错。他说,在 iOS 5 中,UIWebView 会跟踪它自己的保留计数(使用 UIWebViewInternal 类),并且我的方法 swizzling 在对象完全初始化之前保留它,这导致了崩溃。当我不使用 ARC 时,这不是问题,因为我从不在 init 函数中调用保留,但是使用 ARC 它会在“认为”合适时添加保留。他提到在 iOS 6 中 UIWebViews 不管理自己的保留计数,这就是它在 iOS 6 中工作的原因。

于 2013-07-17T21:53:15.660 回答