错误:将非转义参数“ publicationQuery”分配给@转义闭包

Mel*_*ius 5 closures escaping ios swift

我有一个这样的视图控制器:

class PublicationListViewController: UIViewController {
    var publicationQuery: (() -> [Publication])!

    func initWith(title: String, publicationQuery: () -> [Publication]) {
        self.title = title
        self.publicationQuery = publicationQuery
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么会出现“将非转义参数'publicationQuery'分配给@转义闭包”错误?

Mil*_*sáľ 7

逃逸关闭

因为通过将publicationQueryint 存储到属性中,您允许它从初始化程序中“退出”(即使initiiliazer完成执行后,它仍然存在,因此是保留周期的潜在原因)。为此,您必须使用@escaping注释将其显式标记为转义:

class PublicationListViewController: UIViewController {
    var publicationQuery: (() -> [String])!

    // notice that now publicationQuery uses @escaping annotation
    func initWith(title: String, publicationQuery: @escaping () -> [String]) {
        self.title = title
        self.publicationQuery = publicationQuery
    }
}
Run Code Online (Sandbox Code Playgroud)

Closures文档的Escaping Closures部分中了解有关转义的更多信息。

防止保留周期

使用转义闭包时,必须注意不要创建保留周期。最简单的方法是在创建转义转义闭包时使用捕获列表,并且在该捕获列表中显式捕获self作为weak参考:

// use [weak self] capture list to make sure that you don't create another strong reference to self
pubController.initWith(title: "Title") { [weak self] () -> [String] in
    // use guard to safely unwrap the self
    guard let `self` = self else { return }

    // here self will be non-optional value that you can directly use
}
Run Code Online (Sandbox Code Playgroud)