我有一种偶尔崩溃的方法。
-(void)foo{
[self doSomething];
[self.delegate didFinish];
[self doSomethingElse];
}
-doSomething正常工作,然后我调用委托-didFinish。在-didFinish中,对此对象的引用可能设置为nil,在ARC下释放它。当方法崩溃时,它会在-doSomethingElse上执行此操作。我的假设是自我在一个方法中会很强大,允许函数完成。自我弱还是强?有关于此的文件吗?它的强弱是什么原因?
修改
受到以下一些答案的启发,我做了一些调查。在我的情况下崩溃的实际原因是NSNotificationCenter在任何情况下都不保留观察者。 Mike Weller在下面指出方法的调用者应该在调用它时保留对象以防止我上面描述的情况,但是看起来NSNotificationCenter忽略了这个问题,并且始终保持对观察者的弱引用。换句话说:
-(void)setupNotification{
//observer is weakly referenced when added to NSNotificationCenter
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleNotification:)
name:SomeNotification object:nil];
}
//handle the notification
-(void)handleNotification:(id)notification{
//owner has reference so this is fine
[self doSomething];
//call back to the owner/delegate, owner sets reference to nil
[self.delegate didFinish];
//object has been dealloc'ed, crash
[self doSomethingElse];
}
答案 0 :(得分:9)
ARC中{p>自我在一个方法中会很强大,允许该函数完成。自我弱还是强?
self
既不强也不弱。假设呼叫者持有参考,并且 self
是不安全的未保留。
同样正确的是self
可以在ARC自己的方法中-dealloc
,并且它被视为“未定义的行为(或至少是危险的)”,以便您的程序执行此操作。
它强弱的原因是什么?
性能尚无法保证 - 避免(在绝大多数情况下)不必要的引用计数inc / dec。即使他们完成了所有这些额外的引用计数操作,您的程序仍然会在多线程程序中或在存在竞争条件(也是UB)时容易出现此类问题。所以这是他们(正确地)确定他们不需要保护自己的极端边缘案例之一。
有关于此的文件吗?
答案 1 :(得分:4)
self
既不弱也不强。如果您可以访问self
,那么您处于方法调用的范围内,并且该方法调用由某人通过他们必须拥有的引用执行。只要它在范围内,self
就被暗示为有效的引用,并暗示任何内存管理或所有权都由调用者处理。
通过弱引用调用方法时,ARC将在该方法调用期间保留该对象(请参阅this answer)。启用严格的编译器警告后,实际上您将强制在将任何方法发送到该引用之前创建强引用。
因此,根据定义,如果在对象上调用方法,则调用者必须已拥有所有权,并且不需要执行任何操作。
当然,最终可以在解除分配的对象上调用方法,但这是错误的调用者代码的结果。