Weak/Strong 嵌套块中的引用
Weak/Strong reference within nested blocks
我正在尝试找出嵌套块的 weakself/strongself 参考
有什么区别:
__weak __typeof__(self) weakSelf = self;
[self.networkCall_1 completionHandler:^(id response) {
if(response) {
[weakSelf.networkCall_2 completionHandler:^(id response2) {
}];
}
}];
和:
__weak __typeof__(self) weakSelf = self;
[self.networkCall_1 completionHandler:^(id response) {
__typeof__(self) strongSelf = weakSelf;
if(response) {
[strongSelf.networkCall_2 completionHandler:^(id response2) {
}];
}
}];
我的理解是,如果我们不在内部块中使用 strongSelf,self 可能会被释放,因此 networkCall_2 可能为 nil,并且永远不会被调用。如果是这样,如果我不关心 networkCall_2 是否完成,我可以只使用 weakSelf 吗?另外,如果 networkCall_2 是 运行 并且 self 被释放会怎样?它会结束还是终止通话?谢谢!
(@trungduc 接近答案但不幸的是决定删除它。所以现在我可能无意中让你失去了你迄今为止唯一的答案我会看看我是否可以帮助你出。)
此答案仅适用于使用 ARC
What are the difference between:
可能令人惊讶的答案是 在这个特定示例中不是很多...
当 Objective-C 对对象进行方法调用时,它确保该对象在整个调用过程中都处于活动状态。所以在通话中:
[weakSelf.networkCall_2 completionHandler:^(id response2) {...}];
这是 shorthand(使用点表示法)用于:
[[weakSelf networkCall_2] completionHandler:^(id response2) {...}];
首先加载 weakSelf
并对结果持有强引用,将此引用称为 A
。然后在 A
上调用 属性(方法)networkCall_2
,并对其结果进行强引用,称为 B
。此时,编译器可以自由删除强引用 A
,因为它在此时未被使用。最后调用 B
上的方法 completionHandler:
。在 returns 之后,可能在传递的完成块被调用之前,编译器可以随意删除强引用 B
.
如果 A
或 B
高于 nil
那么对它们的调用只是 return nil
并且什么也不会发生。
Note: your code is a little unusual, more common might be something like:
[weakSelf networkCall_2:<some argument> completionHandler:^(id response2) {...}];
that is networkCall_2:completionHandler:
is a method on the object referenced by weakSelf
. If this is what your actual code looks like then the above still applies and the compiler will hold a strong reference across the call to whatever weakSelf
references.
现在转向:
__typeof__(self) strongSelf = weakSelf;
if(response) {
[strongSelf.networkCall_2 completionHandler:^(id response2) {...}];
编译器首先加载 weakSelf
并在 strongSelf
中持有对它的强引用。然后在 strongSelf
上调用 属性(方法)networkCall_2
,并对其结果进行强引用,称为 B
。此时,编译器可以自由删除强引用 strongSelf
,因为它在此时未被使用。等等
(注意:上面两种情况下的“自由丢弃”并不意味着编译器会立即丢弃它,它可能会推迟到 if
或块结束时才丢弃。)
注意到这两个描述的相似之处了吗?在这个特定的例子中,使用weakSelf
和strongSelf
之间确实没有区别。那么为什么有些代码使用 strongSelf
模式呢?考虑:
__typeof__(self) strongSelf = weakSelf;
if (strongSelf) // object still exists)
{
// *all* three methods will be called
[strongSelf method1];
[strongSelf method2];
[strongSelf method3];
}
对比:
[weakSelf method1]; // call method1 if weakSelf is not nil
[weakSelf method2]; // call method2 if weakSelf is *still* not nil
[weakSelf method3]; // call method3 if weakSelf is *still* not nil
使用上面的 strongSelf
模式可确保进行 0 次(如果 weakSelf
为 nil
)或 3 次方法调用。如果使用 weakSelf
模式,可能会调用 0、1、2 或 3 个方法。
您的特定示例具有相同的结果,因为 只有一个 使用 strongSelf
/weakSelf
,在上面的结果可能不同因为 多次 使用 strongSelf
/weakSelf
.
这给我们留下了您的问题:
Also, what happens if networkCall_2
is running, and self
gets deallocated? Does it finish or terminate the call?
这个问题读起来好像 networkCall_2
是一种方法而不是 属性,请参阅上面的注释,我们将涵盖这两种情况:
如果您在这里指的是方法 networkCall_2
的 self
那么如上所述 Objective-C 将在对任何对象的调用中保持强引用一个方法被调用,所以 self
不能在调用期间被释放。因此,活动呼叫永远不会因其 self
消失而终止。
如果你的networkCall_2
确实是一个属性,那么weakSelf
(上面的A
)引用的对象将不会被释放在 属性 调用中,如 (1) 中所示。然而,当随后在 属性 调用 returned(上面的 B
)的任何对象上调用 completionHandler:
方法时,可以在该调用中释放 A
(除非该调用通过其他方式强烈引用 A
)。
希望我正确理解了你的问题,如果是的话,我认为你的答案归结为知道:
An object on which a method (or property) is called will not be deallocated during that method (or property) call.
HTH
我正在尝试找出嵌套块的 weakself/strongself 参考
有什么区别:
__weak __typeof__(self) weakSelf = self;
[self.networkCall_1 completionHandler:^(id response) {
if(response) {
[weakSelf.networkCall_2 completionHandler:^(id response2) {
}];
}
}];
和:
__weak __typeof__(self) weakSelf = self;
[self.networkCall_1 completionHandler:^(id response) {
__typeof__(self) strongSelf = weakSelf;
if(response) {
[strongSelf.networkCall_2 completionHandler:^(id response2) {
}];
}
}];
我的理解是,如果我们不在内部块中使用 strongSelf,self 可能会被释放,因此 networkCall_2 可能为 nil,并且永远不会被调用。如果是这样,如果我不关心 networkCall_2 是否完成,我可以只使用 weakSelf 吗?另外,如果 networkCall_2 是 运行 并且 self 被释放会怎样?它会结束还是终止通话?谢谢!
(@trungduc 接近答案但不幸的是决定删除它。所以现在我可能无意中让你失去了你迄今为止唯一的答案我会看看我是否可以帮助你出。)
此答案仅适用于使用 ARC
What are the difference between:
可能令人惊讶的答案是 在这个特定示例中不是很多...
当 Objective-C 对对象进行方法调用时,它确保该对象在整个调用过程中都处于活动状态。所以在通话中:
[weakSelf.networkCall_2 completionHandler:^(id response2) {...}];
这是 shorthand(使用点表示法)用于:
[[weakSelf networkCall_2] completionHandler:^(id response2) {...}];
首先加载 weakSelf
并对结果持有强引用,将此引用称为 A
。然后在 A
上调用 属性(方法)networkCall_2
,并对其结果进行强引用,称为 B
。此时,编译器可以自由删除强引用 A
,因为它在此时未被使用。最后调用 B
上的方法 completionHandler:
。在 returns 之后,可能在传递的完成块被调用之前,编译器可以随意删除强引用 B
.
如果 A
或 B
高于 nil
那么对它们的调用只是 return nil
并且什么也不会发生。
Note: your code is a little unusual, more common might be something like:
[weakSelf networkCall_2:<some argument> completionHandler:^(id response2) {...}];
that is
networkCall_2:completionHandler:
is a method on the object referenced byweakSelf
. If this is what your actual code looks like then the above still applies and the compiler will hold a strong reference across the call to whateverweakSelf
references.
现在转向:
__typeof__(self) strongSelf = weakSelf;
if(response) {
[strongSelf.networkCall_2 completionHandler:^(id response2) {...}];
编译器首先加载 weakSelf
并在 strongSelf
中持有对它的强引用。然后在 strongSelf
上调用 属性(方法)networkCall_2
,并对其结果进行强引用,称为 B
。此时,编译器可以自由删除强引用 strongSelf
,因为它在此时未被使用。等等
(注意:上面两种情况下的“自由丢弃”并不意味着编译器会立即丢弃它,它可能会推迟到 if
或块结束时才丢弃。)
注意到这两个描述的相似之处了吗?在这个特定的例子中,使用weakSelf
和strongSelf
之间确实没有区别。那么为什么有些代码使用 strongSelf
模式呢?考虑:
__typeof__(self) strongSelf = weakSelf;
if (strongSelf) // object still exists)
{
// *all* three methods will be called
[strongSelf method1];
[strongSelf method2];
[strongSelf method3];
}
对比:
[weakSelf method1]; // call method1 if weakSelf is not nil
[weakSelf method2]; // call method2 if weakSelf is *still* not nil
[weakSelf method3]; // call method3 if weakSelf is *still* not nil
使用上面的 strongSelf
模式可确保进行 0 次(如果 weakSelf
为 nil
)或 3 次方法调用。如果使用 weakSelf
模式,可能会调用 0、1、2 或 3 个方法。
您的特定示例具有相同的结果,因为 只有一个 使用 strongSelf
/weakSelf
,在上面的结果可能不同因为 多次 使用 strongSelf
/weakSelf
.
这给我们留下了您的问题:
Also, what happens if
networkCall_2
is running, andself
gets deallocated? Does it finish or terminate the call?
这个问题读起来好像 networkCall_2
是一种方法而不是 属性,请参阅上面的注释,我们将涵盖这两种情况:
如果您在这里指的是方法
networkCall_2
的self
那么如上所述 Objective-C 将在对任何对象的调用中保持强引用一个方法被调用,所以self
不能在调用期间被释放。因此,活动呼叫永远不会因其self
消失而终止。如果你的
networkCall_2
确实是一个属性,那么weakSelf
(上面的A
)引用的对象将不会被释放在 属性 调用中,如 (1) 中所示。然而,当随后在 属性 调用 returned(上面的B
)的任何对象上调用completionHandler:
方法时,可以在该调用中释放A
(除非该调用通过其他方式强烈引用A
)。
希望我正确理解了你的问题,如果是的话,我认为你的答案归结为知道:
An object on which a method (or property) is called will not be deallocated during that method (or property) call.
HTH