以此代码为例:
import Foundation
class ExampleDataSource {
    var content: Any?
    func loadContent() {
        ContentLoader.loadContentFromSource() { [weak self] loadedContent in
            // completion handler called on background thread
            dispatch_async(dispatch_get_main_queue()) { [weak self] in
                self?.content = loadedContent
            }
        }
    }
}
class ContentLoader {
    class func loadContentFromSource(completion: (loadedContent: Any?) -> Void) {
        /*
        Load content from web asynchronously,and call completion handler on background thread.
        */
    }
} 
 在这个例子中,[weak self]用于两个尾随闭包,但是如果我从尾随闭包中的任何一个省略[weak self],编译器是非常高兴的.
所以我留下了3个选项来定义我的捕获列表:
>在每个嵌套的闭包上定义捕获,导致引用
>仅在第一个闭包上定义捕获.
>仅对实际使用引用的最嵌套的闭包定义捕获.
我的问题是:
If I kNow that my
ExampleDataSourceCould benilat some point,what is the best option to go with?
解决方法
类之间的强引用也不同,也不适用于分配给实例的属性的闭包中的强引用. Apple Documentation
也就是说,在这个例子中,正确的答案是选项2,仅在第一个闭包上定义捕获.
为了测试目的,我稍微修改了代码:
class ExampleDataSource {
    init() {
        print("init()")
    }
    deinit {
        print("deinit")
    }
    var content: Any?
    func loadContent() {
        print("loadContent()")
        ContentLoader.loadContentFromSource() { [weak self] loadedContent in
            dispatch_async(dispatch_get_main_queue()) {
                print("loadedContent")
                self?.content = loadedContent
            }
        }
    }
}
class ContentLoader {
    class func loadContentFromSource(completion: (loadedContent: Any?) -> Void) {
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY,0)) {
            sleep(5)  // thread will hang for 5 seconds
            completion(loadedContent: "some data")
        }
    }
} 
 首先我创建,var myDataSource:ExampleDataSource? = ExampleDataSource().
然后我运行myDataSource.loadContent().
在完成处理程序有机会运行之前,我设置myDataSource = nil,删除对它的所有引用.
调试控制台表示对自身的引用未被保留:
init() loadContent() deinit loadedContent
看起来我们找到了我们的答案!但是为了完成这个目的,让我们来考察替代方案…
如果[weak self]被捕获在只有内部最后面的闭包,GCD将保留ExampleDataSource,直到块完成执行,这就解释了为什么调试看起来像这样:
init() loadContent() loadedContent deinit
同样的事情会发生,如果没有捕获列表被包括,我们从来没有可选地解开自己,尽管编译器,确实试图警告你!
虽然在所有尾随关闭中包含[弱自我]捕获技术上并不是技术上不正确的,但它确实会降低代码的可读性,并且不会感觉到“像Swift一样”.