可选闭包总是会逃逸吗?我们应该使用[weak self]还是[unowned self]呢?

Che*_*eng 2 ios swift

在 中给出以下函数签名UICollectionView

open func performBatchUpdates(_ updates: (() -> Void)?, completion: ((Bool) -> Void)? = nil)
Run Code Online (Sandbox Code Playgroud)

互联网上有一些选项,可选关闭总是会逃脱。但是,我真的不确定这是真的,或者这仍然值得商榷。

  1. https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556
  2. https://gist.github.com/gringoireDM/1f18f3bb4e74e2d914a748d89486db56

对于上述情况,我们是否需要在第一个块中使用[weak self], 或,以及第二个黑色?[unowned self]

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    collectionView!.performBatchUpdates({ () -> Void in
        for operation: BlockOperation in self.blockOperations {
            operation.start()
        }
    }, completion: { (finished) -> Void in
        self.blockOperations.removeAll(keepingCapacity: false)

        self.collectionView.reloadData()
    })
}
Run Code Online (Sandbox Code Playgroud)

Chi*_*red 5

根据编译器(它具有对此类事情唯一重要的“意见”),可选的闭包参数始终是隐式的@escaping。通过编写一个带有可选闭包并将其标记为 的函数来亲自测试这一点@escaping。编译器会通知您它已经转义了。

至于是否应该捕获selfasweakunowned,这取决于情况。首先,我会远离捕获selfas unowned,除非你希望你的程序崩溃,如果你对 - 的生命周期有误的话self- 你可能会这样做。我宁愿我的程序崩溃也不愿默默地做错事。

但这留下了是否捕获 as 的问题weak。我的意见是肯定的,如果您对捕获强引用有任何疑问,请创建一个引用循环以防止其正确取消初始化。但我不会说总是从不做某事。如果您能够推断对象的生命周期,以便知道在通常应取消初始化对象之前将运行并释放闭包,那么只需将其捕获为强引用即可。如果您为了闭包而有意延长对象的生命周期,并且您知道闭包将被执行和处置,也可以通过强引用进行捕获。

还有一种情况是,尽管你隐含地知道@escaping它实际上并没有逃脱。通常这是针对代码库中定义的函数,以便您可以查看实现,但实际上任何时候闭包只是您调用的函数返回之前必须完成的工作的自定义点,您可以推断它实际上并没有逃脱。对于完成处理程序来说情况并非如此,但对于其他事情可能是这样。

这是我的意见。我认为这是一种知情的说法,但其他人可能不同意。