积木中的弱势自我
Weak Self in Blocks
我是否需要检查块中的 weak self 是否为 nil?
我创建 weakSelf 指针如下:
__weak typeof(self) weakSelf = self;
在我做的块的开头
if(!weakSelf){return;}
这是不必要的吗?还是取决于我是否正确编码其余部分,以便当自己死亡时,其他人也会死亡?
这似乎完全没有必要,因为在 nil 上调用消息是空操作。 (没有任何反应)
^{
[weakSelf doSomething]; //Does nothing if weakSelf is nil
}
我认为您可能想要这样做的唯一原因是 其他 消息(不是自己)不应该被调用
^{
// Here I don't want to add weakSelf as an observer if it's nil
if (!weakSelf) return;
[OtherClass addObserverForSomething:weakSelf];
}
这种检查是不必要的,会给你一种错误的安全感。
这是问题所在:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
if (!weakSelf) { return; }
// THE LINE OF INTEREST
[weakSelf doSomething];
});
在 THE LINE OF INTEREST
,一些其他线程可能会清除对 self
的最后一个强引用,此时 weakSelf
被设置为 nil。所以 doSomething
消息被发送到 nil,这是“安全的”(它什么都不做),但可能不是你所期望的!
如果您想在 weakSelf
为 nil 时采取不同的操作,情况会更糟,例如
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf) {
[weakSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
在这种情况下,在块验证 weakSelf
不为 nil 和它发送 doSomething
消息的时间之间,weakSelf
可能变为 nil,并且 doSomething
和 doSomethingElse
实际上都不会 运行.
正确的解决方法是:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
在这种情况下,将 weakSelf
复制到 strongSelf
(默认情况下是强的)是原子的。如果 weakSelf
为 nil,则 strongSelf
将为 nil。如果 weakSelf
不是 nil,strongSelf
将不会是 nil,并且将是对象的强引用,防止它在 doSomething
消息之前被释放。
弱引用不保留被引用的对象。如果 none else 正在保留它,则对象被释放并且弱引用引用 nil
.
因此,您的代码可能是使用引用 nil
的 weakSelf
执行的。但这根本不是检查它的理由。特别是在 Objective-C 中,如果您发送消息 nil
,您将使用定义的行为。 IE。如果您使用 nil
引用设置 属性,那么它就是完美的代码。它只是无处可去。
当然有时您不想与 nil
互动。在这种情况下,您必须检查它。
顺便说一句:您只在某些情况下才需要 weakSelf
。这是一个都市传说,在闭包中,一般引用 self
必须很弱以防止保留循环。这不是真的,这不是真的,永远不会是真的。
我是否需要检查块中的 weak self 是否为 nil?
我创建 weakSelf 指针如下:
__weak typeof(self) weakSelf = self;
在我做的块的开头
if(!weakSelf){return;}
这是不必要的吗?还是取决于我是否正确编码其余部分,以便当自己死亡时,其他人也会死亡?
这似乎完全没有必要,因为在 nil 上调用消息是空操作。 (没有任何反应)
^{
[weakSelf doSomething]; //Does nothing if weakSelf is nil
}
我认为您可能想要这样做的唯一原因是 其他 消息(不是自己)不应该被调用
^{
// Here I don't want to add weakSelf as an observer if it's nil
if (!weakSelf) return;
[OtherClass addObserverForSomething:weakSelf];
}
这种检查是不必要的,会给你一种错误的安全感。
这是问题所在:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
if (!weakSelf) { return; }
// THE LINE OF INTEREST
[weakSelf doSomething];
});
在 THE LINE OF INTEREST
,一些其他线程可能会清除对 self
的最后一个强引用,此时 weakSelf
被设置为 nil。所以 doSomething
消息被发送到 nil,这是“安全的”(它什么都不做),但可能不是你所期望的!
如果您想在 weakSelf
为 nil 时采取不同的操作,情况会更糟,例如
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf) {
[weakSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
在这种情况下,在块验证 weakSelf
不为 nil 和它发送 doSomething
消息的时间之间,weakSelf
可能变为 nil,并且 doSomething
和 doSomethingElse
实际上都不会 运行.
正确的解决方法是:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
在这种情况下,将 weakSelf
复制到 strongSelf
(默认情况下是强的)是原子的。如果 weakSelf
为 nil,则 strongSelf
将为 nil。如果 weakSelf
不是 nil,strongSelf
将不会是 nil,并且将是对象的强引用,防止它在 doSomething
消息之前被释放。
弱引用不保留被引用的对象。如果 none else 正在保留它,则对象被释放并且弱引用引用 nil
.
因此,您的代码可能是使用引用 nil
的 weakSelf
执行的。但这根本不是检查它的理由。特别是在 Objective-C 中,如果您发送消息 nil
,您将使用定义的行为。 IE。如果您使用 nil
引用设置 属性,那么它就是完美的代码。它只是无处可去。
当然有时您不想与 nil
互动。在这种情况下,您必须检查它。
顺便说一句:您只在某些情况下才需要 weakSelf
。这是一个都市传说,在闭包中,一般引用 self
必须很弱以防止保留循环。这不是真的,这不是真的,永远不会是真的。