Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/121.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如果从块调用的方法使用self,是否需要使用弱self指针?_Ios_Objective C_Objective C Blocks_Retain Cycle - Fatal编程技术网

Ios 如果从块调用的方法使用self,是否需要使用弱self指针?

Ios 如果从块调用的方法使用self,是否需要使用弱self指针?,ios,objective-c,objective-c-blocks,retain-cycle,Ios,Objective C,Objective C Blocks,Retain Cycle,在块中使用self.会导致保留循环,因此我需要创建对weakSelf的引用。我明白这一点 但是 如果从我的块调用一个使用self“,这是否也会导致保留周期?例如,如果我从一个块重新加载UITableView,并且在我调用self.的一些UITableView委托方法中,我是否导致了一个保留周期?这是否意味着我必须到处传递这个弱引用?似乎是胡言乱语。首先:self是否会导致保留周期。这是一个都市传奇。这种不正确是显而易见的:一个单一的引用永远不会导致循环。如果块也被self直接或间接引用(例如通过

在块中使用
self.
会导致保留循环,因此我需要创建对
weakSelf
的引用。我明白这一点

但是


如果从我的块调用一个使用
self
“,这是否也会导致保留周期?例如,如果我从一个块重新加载
UITableView
,并且在我调用
self.
的一些
UITableView
委托方法中,我是否导致了一个保留周期?这是否意味着我必须到处传递这个弱引用?似乎是胡言乱语。

首先:
self
是否会导致保留周期。这是一个都市传奇。这种不正确是显而易见的:一个单一的引用永远不会导致循环。如果块也被
self
直接或间接引用(例如通过属性),则在块内使用
self
会导致保留循环

对你的问题:

如果在块内“调用”一个方法,则消息可能具有接收方
self
,因此在块内使用
self
。因此,它被捕获并保留


如果通过既不使用
self
也不使用
self
属性,在块内确实没有使用
self
,则没有使用
self
,因此不会保留。但是在这种情况下,您可以有一个悬空指针或一个零引用。

在执行块时,您不需要担心引用问题-最终它完成了它所做的任何事情,所有这些引用都消失了

您需要担心的是创建块时捕获的引用。这些引用将一直保留到块消失为止。因此,如果你的块有一个对“self”的引用,这个引用就是因为块存在而存在的。如果你把这个块存储在self属性中,你就有了一个循环


因此,如果将块作为属性存储在self中,则该块不应捕获self。通过让它访问并捕获自我的弱拷贝,这很容易做到。请记住,当执行块时,self的弱副本可能为nil。这意味着self对象已经离开了我们的世界,而你的block可能不需要做任何事情

简短回答:不,在这种情况下,不会保留自我

长答案

首先,保持自我和参考周期不是一回事。引用循环是多个对象之间的强引用循环:a->B->C->a是保留循环

一般的想法是,您希望始终保证,如果您在块中引用self,那么您不会强引用该块,也不会通过一系列强引用来引用它。实际上,如果您确保在某些条件下打破保留周期,则可以有目的地使用保留周期。我个人并不建议这样做

看一看。它清楚地表明,值是在块中捕获的,而捕获对象引用会将该对象保留在块中

基本上,这意味着引用块中的对象会将其重新计数增加1,当该块被释放时,重新计数会减少1

但是,在块中使用_弱指针时,保留计数是不变的

下面是一个例子:

- (void) doSomething {
   NSLog(@"%@", self);
}

- (void) callBlock {
   __weak typeof(self) weakSelf = self;
   dispatch_block_t block = ^{
      [weakSelf doSomething];
   };
}
当您编写
[obj方法:params]
时,这实际上转化为以下调用:
objc\u msgSend(obj,@选择器(方法:),参数)
。Objective-C的一个特性是,如果调用nil指针上的方法,它将返回nil。这是由以下事实保证的:
objc_msgSend(nil,@selector(anyselector),…)
始终返回nil。请注意,SEL只是封面下的const char[],因此它不会以任何方式影响保留计数

因此,当执行块时,如果对象被解除分配,弱
weakSelf
变量将被置零,块体将转换为objc_msgSending为零,这除了浪费很少的CPU周期外,什么都不做


总之,Objective-C消息传递系统的实现方式是,调用方法不会保留此对象、此方法或此方法的实现,因为它是一个简单的函数调用

我可能误解了你的问题,但你的措辞:

如果从我的块调用一个使用“self”的方法,这是否也会导致一个retain循环?例如,如果我从一个块重新加载一个UITableView,并且在我的一些UITableView委托中我称之为“self”,那么我是否导致了一个保留周期?那就意味着我必须在任何地方都传递这个weakReference

表明您误解了
self
是什么。如果是这样的话,希望下面的内容能帮助你,而不是阻碍你的理解

什么是
self

标识符self只是方法的一个参数的名称,它只是隐式传递,而不是像其他参数一样显式传递。例如,如果您有一个类:

@implementation MyClass

- (void) someMethod:(NSInteger)value
{
   ... self ... value
}

@end
然后,该方法是有效的(即,为了清楚起见,稍微歪曲事实):

调用实例方法时,为
self
参数传递的值是对该方法应操作的实例的引用,例如调用

MyClass *someInstance = ...

[someInstance someMethod:42];
实际上是呼吁:

someMethod:42 withObject:someInstance
强参考周期

只要存在对对象的强引用,对象(包括类和块的实例)就会保持活动状态

如果对象
A
持有对对象
B
的强引用(例如在实例变量或属性中),则只要
A
处于活动状态,
B
至少将保持活动状态(可能存在对
B
的其他强引用)

如果对象
A
具有对
B
的强引用
someMethod:42 withObject:someInstance