3

我在 UIViewController 上定义了以下属性:

@property (nonatomic, strong) UIButton *strongButton;
@property (nonatomic, weak) UIButton *weakButton;

这些属性不是通过 Interface Builder 设置的(即,只要我没有在代码中明确设置它们,它们将始终保持为 nil)。

我还在 UIButton 上添加了一个类别,以准确了解它何时被释放:

@implementation UIButton (test)
- (void)dealloc { NSLog(@"Dealloc called."); }
@end

viewDidLoad我在 UIViewController中有以下代码:

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) 上失败。日志显示:

  • 设置为零
  • 完成设置为零
  • * -[ViewController viewDidLoad] 中的断言失败
  • *由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“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 打来电话。
  • 完成设置为零

请注意在第一个场景中没有在适当的时间调用 dealloc。

为什么第一个 NSAssert 会导致这种奇怪的行为?这是一个错误还是我做错了什么?

(我在 iOS 6.1 上)

4

1 回答 1

7

读取弱变量可能会导致指向的对象被保留和自动释放。然后,该对象将至少与当前的自动释放池一样长。

在您的情况下,您首先NSAssert()读取弱变量。按钮对象被保留并自动释放。设置self.strongButton=nil不会导致按钮被释放,因为它在自动释放池中还活着,所以weak变量不会变成nil。

当您注释掉 时NSAssert(),不再读取弱变量,因此按钮不会保留和自动释放,因此实际上在您设置时它确实会死掉self.strongButton=nil

于 2013-07-30T01:26:06.737 回答