带块的保留循环
The retain cycle with block
关于块的保留循环的问题。在 ARC 模型中。
比如说,一个名为 'vc' 的视图控制器实例,它持有对一个块的引用。在块中,vc 用于某些操作:
{
//this is a piece of code snippet in vc
self.vcBlock = {
[self someAction];
}
}
我知道这会导致保留周期,因为 vc 持有对块的强引用,而块也会持有对 vc 的强引用。
但是如何在块中引用 vc 的成员变量:
{
//this is a piece of code snippet in vc
self.vcBlock = {
[self.obj someAction];
}
}
这会导致保留循环吗?我认为这些引用的关系可以解释如下:
所以,我认为不存在循环引用,有什么问题吗?
属性 访问在编译时被转换为方法调用,所以在你的第二个例子中,它仍然是 self 被保留,并且你有完全相同的循环。
它确实存在循环引用,vcBlock holds a strong reference to self(the vc),
或者你可以把它当作
[[self obj] someAction];
如果我们像这样以另一种形式调用这个方法(如果 obj 是一个 ivar)
[_obj someAction];//in fact ,it's equivalent to [self->obj someAction]
因此块始终持有对 self 的强引用。
第二种情况,可以避免retain cycle:
{
MyObject* obj = self.obj;
self.vcBlock = ^{ [obj someAction]; };
}
表达式self.obj
是在运行时计算的,这需要块保持self
的值,所以你仍然有一个循环。
但是,如果您的图表是您想要的关系,那就是您的块具有对对象的引用,该对象在创建块时被 self.obj
引用 那么你可以简单地通过使用一个临时局部变量来实现。 IE。代码如下:
SomeType objRef = self.obj;
self.vcBlock = ^{ ... [objRef someAction]; ... };
这避免了循环,因为 self.obj
返回的 value(对象引用)首先被复制到本地 objRef
,然后 value 成为块保存值的一部分(也就是它的 environmemt)。
在这种情况下,这是一种常见的方法,但请记住,如果 self.obj
的值在块执行之前发生变化,那么该变化将 不会被看到 按块 - 这似乎是您希望从图表中看到的。
另请注意,循环 本身 不是问题,您可以创建循环并在稍后打破它们而不会出现问题 - 实际上这并不少见。一个循环只有在导致未回收资源(如内存)时才是问题。
HTH
关于块的保留循环的问题。在 ARC 模型中。
比如说,一个名为 'vc' 的视图控制器实例,它持有对一个块的引用。在块中,vc 用于某些操作:
{
//this is a piece of code snippet in vc
self.vcBlock = {
[self someAction];
}
}
我知道这会导致保留周期,因为 vc 持有对块的强引用,而块也会持有对 vc 的强引用。
但是如何在块中引用 vc 的成员变量:
{
//this is a piece of code snippet in vc
self.vcBlock = {
[self.obj someAction];
}
}
这会导致保留循环吗?我认为这些引用的关系可以解释如下:
所以,我认为不存在循环引用,有什么问题吗?
属性 访问在编译时被转换为方法调用,所以在你的第二个例子中,它仍然是 self 被保留,并且你有完全相同的循环。
它确实存在循环引用,vcBlock holds a strong reference to self(the vc), 或者你可以把它当作
[[self obj] someAction];
如果我们像这样以另一种形式调用这个方法(如果 obj 是一个 ivar)
[_obj someAction];//in fact ,it's equivalent to [self->obj someAction]
因此块始终持有对 self 的强引用。
第二种情况,可以避免retain cycle:
{
MyObject* obj = self.obj;
self.vcBlock = ^{ [obj someAction]; };
}
表达式self.obj
是在运行时计算的,这需要块保持self
的值,所以你仍然有一个循环。
但是,如果您的图表是您想要的关系,那就是您的块具有对对象的引用,该对象在创建块时被 self.obj
引用 那么你可以简单地通过使用一个临时局部变量来实现。 IE。代码如下:
SomeType objRef = self.obj;
self.vcBlock = ^{ ... [objRef someAction]; ... };
这避免了循环,因为 self.obj
返回的 value(对象引用)首先被复制到本地 objRef
,然后 value 成为块保存值的一部分(也就是它的 environmemt)。
在这种情况下,这是一种常见的方法,但请记住,如果 self.obj
的值在块执行之前发生变化,那么该变化将 不会被看到 按块 - 这似乎是您希望从图表中看到的。
另请注意,循环 本身 不是问题,您可以创建循环并在稍后打破它们而不会出现问题 - 实际上这并不少见。一个循环只有在导致未回收资源(如内存)时才是问题。
HTH