1

我目前正在修复一个不是用 ARC 构建的遗留应用程序上的一些 iOS 7 显示问题,并且dealloc在 iOS 版本 6 和 7 之间遇到了一些不一致的行为。我找不到任何其他提及这些任何文档或社区讨论的变化,所以我想知道这里是否有人可以对这里发生的事情有所了解?

我之前的代码(在 iOS6 中工作,如下所示):

@interface MyViewController()
@property (retain) AdHandler *adHandler;
@end

@implementation MyViewController

@synthesize adHandler = _adHandler;

- (id) initWithAdHandler:(AdHandler*)anAdHandler
{
    self = [super init];
    _adHandler = [anAdHandler retain];
    return self;
}

- (void)dealloc
{    
    [super dealloc];

    [_adHandler release];
    _adHandler = nil;
}

...

@end

在 iOS 6 中单步执行代码时,我发现在dealloc声明之后,[_adHandler retainCount]仍然是肯定的,并且对象仍然可用。

然而,在 iOS 7 中,在dealloc声明之后,retainCount不知何故达到零,并且该_adHandler对象已被dealloc'd,因此我的调用release导致EXC_BAD_ACCESS.

我可以简单地通过将我[adHandler release]的呼叫移至呼叫之前来解决这个dealloc问题,但我的问题是为什么会发生这种情况?为什么要dealloc释放它不负责的对象?是否有任何文档说明为什么 dealloc 行为会以这种方式发生变化?

4

2 回答 2

6

[super dealloc]实例是垃圾之后,发生的任何事情都是相当随机和不确定的。正如@bneely 所写,[super dealloc]必须是最后一个。

最佳实践:转换为 ARC。

至于retainCount,不能保证它的值是多少,不要使用它,它只会造成混乱。在您的情况下,您通过调用销毁了类实例[super dealloc],然后期望该实例的行为就好像它仍然存在一样。它不能,它已被破坏,现在只是内存中的一些非确定性位。

于 2013-09-26T10:57:08.807 回答
0

永远不应该使用保留计数。

您无法以任何合理的方式解释它返回的值。因此,完全可以预期在不同的 iOS 版本、设备、不同的代码位数等上看到不同的结果。


顺便说一句,您是否考虑切换到 ARC?代码将大大简化。另请注意,如果您正在实现 的子类UIViewController,则不应使用 对其进行初始化init。而只是声明该属性,ARC 将处理它的 setter 和 getter:

@interface MyViewController : UIViewController
@property AdHandler *adHandler;
@end

// somewhere else 
MyViewController * mvc = ... from nib or in some other way ...
mvc.adHandler = myAdHandler;

现在你可以保证没有错误的访问。

于 2013-09-26T10:54:28.607 回答