我在UIViewController上定义了以下属性:
@property (nonatomic, strong) UIButton *strongButton;
@property (nonatomic, weak) UIButton *weakButton;
这些属性不是通过Interface Builder设置的(即只要我没有在代码中明确设置它们,它们将始终保持为零)。
我还在UIButton上添加了一个类别,以确切知道它何时被解除分配:
@implementation UIButton (test)
- (void)dealloc { NSLog(@"Dealloc called."); }
@end
我在UIViewController的viewDidLoad
中有以下代码:
self.strongButton = [[UIButton alloc] init];
self.weakButton = self.strongButton;
NSAssert(self.weakButton != nil, @"A: Weak button should not be nil.");
NSLog(@"Setting to nil");
self.strongButton = nil;
NSLog(@"Done setting to nil");
NSAssert(self.weakButton == nil, @"B: Weak button should be nil.");
当我运行该代码时,在第二个断言(B)上失败。日志显示:
然而,当我评论第一个断言时:
self.strongButton = [[UIButton alloc] init];
self.weakButton = self.strongButton;
//NSAssert(self.weakButton != nil, @"A: Weak button should not be nil.");
NSLog(@"Setting to nil");
self.strongButton = nil;
NSLog(@"Done setting to nil");
NSAssert(self.weakButton == nil, @"B: Weak button should be nil.");
代码在日志中正常运行:
注意在第一个场景中如何在适当的时间调用dealloc。
为什么第一个NSAssert会导致这种奇怪的行为?这是一个错误还是我做错了什么?
(我在iOS 6.1上)
答案 0 :(得分:7)
读取弱变量可能会导致指向对象被保留并自动释放。然后,对象将保持活动状态,至少与当前自动释放池一样长。
在您的情况下,您的第一个NSAssert()
读取弱变量。按钮对象被保留并自动释放。设置self.strongButton=nil
不会导致按钮被释放,因为它在自动释放池中仍然存在,因此弱变量不会变为零。
当您注释掉NSAssert()
时,弱变量不再被读取,因此该按钮不会被保留并自动释放,因此当您设置self.strongButton=nil
时它确实会死亡。