弱属性没有设置为nil [duplicate]

时间:2021-07-21 05:15:41

This question already has an answer here:

这个问题已经有了答案:

I have the following properties defined on a UIViewController:

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

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

These properties are not set via Interface Builder (i.e. they will always remain nil as long as I don't set them explicitly in code).

这些属性不是通过接口构建器来设置的(也就是说,只要我不在代码中显式地设置它们,它们将始终保持为nil)。

I also added a category on UIButton to know exactly when it is dealloced:

我还在UIButton上添加了一个类别来确切地知道它何时被释放:

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

I have the following code in the viewDidLoad of the UIViewController:

我在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.");

When I run that code, it fails on the second assertion (B). The log shows:

当我运行该代码时,它在第二个断言(B)上失败。

  • Setting to nil
  • 设置为零
  • Done setting to nil
  • 完成设置为零
  • * Assertion failure in -[ViewController viewDidLoad]
  • *在-[ViewController viewDidLoad]中断言失败
  • * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'B: Weak button should be nil.'
  • *因未捕获异常“NSInternalInconsistencyException”而终止app,原因:“B:弱按钮应为nil”。

However, when I comment out the first assertion:

然而,当我注释掉第一个断言时:

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.");

The code runs fine with this in the log:

该代码在日志中运行良好:

  • Setting to nil
  • 设置为零
  • Dealloc called.
  • Dealloc调用。
  • Done setting to nil
  • 完成设置为零

Notice how the dealloc is not being called at the proper time in the first scenario.

请注意,在第一个场景中,dealloc是如何在适当的时间被调用的。

Why is that first NSAssert causing this weird behavior? Is this a bug or am I doing something wrong?

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

(I am on iOS 6.1)

(我上的是iOS 6.1)

1 个解决方案

#1


7  

Reading a weak variable may cause the pointed-to object to be retained and autoreleased. The object will then remain alive at least as long as the current autorelease pool.

读一个弱变量可能会导致指向对象被保留,并且自动生成。然后,对象将保持活动状态,至少与当前的自动上传池一样长。

In your case, your first NSAssert() reads the weak variable. The button object is retained and autoreleased. Setting self.strongButton=nil does not cause the button to be deallocated, because it is still alive in the autorelease pool, so the weak variable does not become nil.

在您的示例中,第一个NSAssert()读取弱变量。保留并自动加载按钮对象。设置自我。strongButton=nil不会导致按钮被释放,因为它仍然存在于autorelease池中,所以弱变量不会变成nil。

When you comment out the NSAssert(), the weak variable is no longer read, so the button is not retained and autoreleased, so it does in fact die when you set self.strongButton=nil.

当您注释掉NSAssert()时,弱变量将不再被读取,因此不会保留按钮并自动加载,因此当您设置self.strongButton=nil时,它实际上就会死亡。

#1


7  

Reading a weak variable may cause the pointed-to object to be retained and autoreleased. The object will then remain alive at least as long as the current autorelease pool.

读一个弱变量可能会导致指向对象被保留,并且自动生成。然后,对象将保持活动状态,至少与当前的自动上传池一样长。

In your case, your first NSAssert() reads the weak variable. The button object is retained and autoreleased. Setting self.strongButton=nil does not cause the button to be deallocated, because it is still alive in the autorelease pool, so the weak variable does not become nil.

在您的示例中,第一个NSAssert()读取弱变量。保留并自动加载按钮对象。设置自我。strongButton=nil不会导致按钮被释放,因为它仍然存在于autorelease池中,所以弱变量不会变成nil。

When you comment out the NSAssert(), the weak variable is no longer read, so the button is not retained and autoreleased, so it does in fact die when you set self.strongButton=nil.

当您注释掉NSAssert()时,弱变量将不再被读取,因此不会保留按钮并自动加载,因此当您设置self.strongButton=nil时,它实际上就会死亡。