我正在试图弄清楚嵌套块的弱自己/自我引用
有什么区别:
__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被取消分配,会发生什么?是完成还是终止通话?谢谢!
答案 0 :(得分:2)
(@ trungduc接近答案,但不幸的是已经决定删除它。所以现在因为我可能无意中帮助你失去了你唯一的答案,我会看看我是否可以帮助你。 )
此答案仅适用于使用ARC
有什么区别:
可能令人惊讶的答案是,在这个特定的例子中 并不是很多......
当Objective-C对对象进行方法调用时,它确保对象在整个调用中处于活动状态。所以在电话中:
[weakSelf.networkCall_2 completionHandler:^(id response2) {...}];
是:用点符号表示:
[[weakSelf networkCall_2] completionHandler:^(id response2) {...}];
首先加载weakSelf
并对结果保持强引用,调用此引用A
。然后在networkCall_2
上调用属性(方法)A
,并对其结果进行强引用,调用此B
。此时,编译器可以自由删除强引用A
,因为它未通过此点使用。最后调用completionHandler:
上方法B
的调用。在返回之后,可能在调用传递的完成块之前,编译器可以放弃强引用B
。
如果A
或B
高于nil
,那么对它们的调用只会返回nil
并且没有任何进展。
注意:您的代码有点不寻常,更常见的可能是:
[weakSelf networkCall_2:<some argument> completionHandler:^(id response2) {...}];
networkCall_2:completionHandler:
是weakSelf
引用的对象的方法。如果这是您的实际代码的样子,那么上述内容仍然适用,并且编译器将在调用任何weakSelf
引用时保留强引用。
现在转到:
__typeof__(self) strongSelf = weakSelf;
if(response) {
[strongSelf.networkCall_2 completionHandler:^(id response2) {...}];
编译器首先加载weakSelf
并在strongSelf
中保存对它的强引用。然后在networkCall_2
上调用属性(方法)strongSelf
,并对其结果进行强引用,调用此B
。此时,编译器可以自由删除强引用strongSelf
,因为它未通过此点使用。等
(注意:&#34;可以自由删除&#34;在上述两种情况下并不意味着编译器会立即删除它,它可能会推迟到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];
}
VS
[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
。
这给我们留下了你的问题:
此外,如果
networkCall_2
正在运行,并且self
被取消分配,会发生什么?完成或终止通话吗?
这个问题看起来好像networkCall_2
是一种方法而不是属性,请参阅上面的注释,我们将涵盖这两种情况:
如果您指的是方法self
的{{1}},那么如上所述,Objective-C将对调用方法的任何对象的调用保持强引用,所以networkCall_2
在通话期间无法解除分配。因此,由于self
消失,所以永远不会终止有效通话。
如果self
确实是显示的属性,那么networkCall_2
引用的对象(上面的weakSelf
)将不会在属性调用中被释放,如( 1)。但是,当然后在属性调用返回的任何对象(上面的A
)上调用completionHandler:
方法时,可以在该调用中释放B
(除非该调用具有对{{的强引用) 1}}通过其他方式)。
希望我能正确理解你的问题,如果是的话,我认为你的答案归结为知道:
在该方法(或属性)调用期间,不会释放调用方法(或属性)的对象。
HTH