快速闭包内的自我引用有时会返回零

San*_*ngh 2 weak-references completionhandler swift

我正在快速访问闭包内的实例方法,在某些情况下引用变为,这会导致我的程序崩溃。我尝试访问 using但在self[weak self]时无法调用实例方法。nil

[weak self] () -> () in
Run Code Online (Sandbox Code Playgroud)

Dav*_*rry 5

重点[weak self]是不创建对 self 的引用(可能是为了避免循环链接和内存泄漏),以便可以释放它。如果发生这种情况,那么self将会是nil

您应该要么不使用,要么更好的是,准备好处理已发布并设置为 的[weak self]情况。selfnil

guard let strong = self else { return }
Run Code Online (Sandbox Code Playgroud)

举个例子:

import UIKit
import PlaygroundSupport

class Foo {
    let name : String

    init(name:String) {
        self.name = name

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
            print(self!.name)
        }
    }
}

Foo(name:"freddie")

PlaygroundPage.current.needsIndefiniteExecution = true
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您会崩溃,因为 self 在异步回调执行之前被释放。

您可以将asyncAfter呼叫更改为:

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            print(self.name)
        }
Run Code Online (Sandbox Code Playgroud)

将保证 self 在回调完成之前不会被释放。

或者你可以使用类似的东西:

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
            guard let strong = self else { print("self released") ; return }
            print(strong.name)
        }
Run Code Online (Sandbox Code Playgroud)