在Clang's Objective-C Automatic Reference Counting中,我们看到以下内容
对于__weak对象,左值更新为指向新的指针,除非新指针是当前正在进行解除分配的对象,在这种情况下,左值更新为空指针。这必须相对于对象的其他赋值,从对象读取以及新指针的最终版本以原子方式执行。
在objc-weak.mm中,我们会看到weak_register_no_lock()
中的以下代码块:
if (deallocating) {
if (crashIfDeallocating) {
_objc_fatal("Cannot form weak reference to instance (%p) of "
"class %s. It is possible that this object was "
"over-released, or is in the process of deallocation.",
(void*)referent, object_getClassName((id)referent));
} else {
return nil;
}
}
我在我的UIViewController子类dealloc
方法中设置了一个断点,并尝试在lldb中调用[self allowsWeakReference]
,这导致NO
值。
如果我们尝试将self设置为另一个对象的weak属性,应用程序将根据objc-weak.mm代码崩溃。
问题是 - 为什么会这样?铿锵的规格是错的吗?这是objc实现中的错误吗?
这是一段简单的代码,可以重现崩溃:
//cc -fmodules -fobjc-arc -g crash.m -o crash
@import Foundation;
@interface Foo : NSObject
@end
@implementation Foo
- (void)dealloc {
Foo * __weak weakSelf = self; // crashes on this line
}
@end
int main() {
(void)[[Foo alloc] init];
return 0;
}
答案 0 :(得分:1)
这不是一个错误:它显然是非常有意的。这是对规范的偏差,但它是故意的。
根据警告,听起来他们想要更容易诊断过度发布方案,并且捕获当时正在解除分配的对象可能只是该主要目标的副作用。
他们也可能会考虑,如果你试图在解除分配的同时弱化self
,并且你没有检查nil
弱点(很常见 - 很多块码反复调用通过一个可以随时nil
的弱点!),你正在努力调试bug。
所有这一切,我希望看到运行时改变背后的注释。