关闭时强,弱,无主的自我解释

时间:2017-09-26 11:20:13

标签: swift closures automatic-ref-counting

我需要一些关于Swift中闭包引用的解释。 这是我的用例,让我们想象一下:

class A {...}
class B {

  func makeAclosure() {
   let instanceA = A()
   instanceA.someFunctionA(completion: {(input) in 
     self.someAnotherFunction(input)
   })
  }
}

A类和B类之间是否存在保留周期? 在这种情况下,它可以是一种保留周期吗?

2 个答案:

答案 0 :(得分:3)

如果在调用闭包之前可能会释放self对象,则应指定[weak self],以便避免错误的访问异常。

如果您知道肯定未被取消分配,那么您可以使用[unowned self]创建一个行为类似于隐式展开的可选项的引用。

在您的示例中,B的实例拥有对instanceA的引用(在您的makeAClosure()函数的上下文中),因此您不会以保留周期结束。< / p>

您应该考虑someFunctionA(completion:)的实施,以确定在该关闭中是否需要unownedweakself的引用。

(小一点:如果您正在使用[weak self],那么为了避免代码中包含self?等选项,您可以使用guard let `self` = self else { ... }继续在闭包代码中使用self

答案 1 :(得分:2)

如果A.someFunctionA completion @escaping @escaping未知,则无法查看self是不可能的(例如,如果它被保留)。对于答案的其余部分,我将假设它是self

Swift需要确保运行时的安全性,并保留将来可能需要的任何对象,在这种情况下,强制引用instanceA(因为instanceA是内部使用的唯一变量关闭)。

在这种情况下,没有参考周期。这是因为B未被保留,因此A =&gt; B,但B!=&gt;甲

但是,如果instanceA: A保留了weak(假设您创建了unowned属性并设置了它),那么您将有一个保留周期。

要解决此问题,您可以在闭包中创建变量instanceAB。他们都做同样的事情,但为您提供略有不同的类型。它们都包含弱引用,这意味着B不会增加instanceA实例的引用计数;如果[weak self]已取消分配且没有其他引用,则self也会被取消分配。

使用optional self: B?[unowned self]self: B!,例如self。但是,nil是明确解开的,例如unowned。这意味着如果调用闭包并且BA,则程序将崩溃。这就是为什么只有在您确定解除分配unowned还会释放weak时才使用foreach $result if $results Jan to March $new_results_jm += $results end if $results March to Jun $new_results_mj += $results end end //table head foreach $new_results_jm //table body end //table head foreach $new_results_mj //table body end 这一点非常重要。在某些情况下def get_table_head() //create table head return $table_head end def get_table_body($results) //create table body with $results return $table_body end def get_result(...) //your SELECT return $result end def main() //Jan to March $result = get_result(...) get_table_head() get_table_body($result) //March to Jun $result1 = get_result(...) $result2 = get_result(...) get_table_head() get_table_body($result1) get_table_body($result2) end 是安全的,例如创建一个闭包并将其存储在创建它的同一个对象上的情况,但是有更多的细微差别。

如果不确定,请使用def main() foreach time_range $results[i] = get_result(...) end foreach $results get_table_head() get_table_body($results[i]) end end