关闭时对属性的引用需要明确的"自我".使捕获语义显式化

Thi*_*ark 8 swift swift2

尝试将HTML从Web服务加载到webview中,我收到此错误:

在闭包中引用属性"webviewHTML"需要明确的"自我".使捕获语义显式化

它是什么意思,我如何将HTML字符串加载到我的Web视图中?

func post(url: String, params: String) {

    let url = NSURL(string: url)
    let params = String(params);
    let request = NSMutableURLRequest(URL: url!);
    request.HTTPMethod = "POST"
    request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            print("error=\(error)")
            return
        }

        var responseString : NSString!;
        responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
        webviewHTML.loadHTMLString(String(responseString), baseURL: nil)
    }
    task.resume();
}
Run Code Online (Sandbox Code Playgroud)

Vat*_*not 9

用法self是在闭包中引用(也称为捕获)构造(类/结构/枚举)的显式确认,其含义是self在解除分配所述闭包之前不会释放.

当你想到它时,self可以很好地推断出(当你webviewHTML在闭包之外使用时),但这是一个故意的设计决定,不推断它,因为Swift是一种安全第一语言.


Hon*_*ney 8

在回答这个问题之前,你必须知道记忆周期是什么.请参阅从Apple的文档中解决类实例之间的强引用循环


现在您知道内存周期是什么了:

那个错误是Swift编译器告诉你的

"嘿,NSURLSession 关闭试图 webviewHTML 保留在堆中,因此自我 ==>创建一个内存周期,我不认为Mr.Clark想要这个.想象一下,如果我们提出一个需要永远然后用户导航的请求离开这个页面.它不会离开堆.我只是告诉你这个,但是你的Mr.Clark必须创建一个弱的自我引用并在封闭中使用它."

我们使用创建(即捕获)引用[weak self].我强烈建议您查看附加链接的捕获方式.

欲了解更多信息,请参阅斯坦福课程的这一刻.

正确的代码

func post(url: String, params: String) {

    let url = NSURL(string: url)
    let params = String(params);
    let request = NSMutableURLRequest(URL: url!);
    request.HTTPMethod = "POST"
    request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        [weak weakSelf self] data, response, error in

        if error != nil {
            print("error=\(error)")
            return
        }

        var responseString : NSString!;
        responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) 

        weakSelf?.webviewHTML.loadHTMLString(String(responseString), baseURL: nil)
        // USED `weakSelf?` INSTEAD OF `self` 
    }
    task.resume();
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此内容我们总是在Swift中使用[unowned self]内部闭包

  • 这里有一些微妙之处。斯坦福课程的视频使用 [weak self] 来防止视图被保留在堆上,这是为了不删除引用循环。只有当闭包引用 self 并且 self 保持对闭包的引用时才会发生循环(Apple 文档中明确说明了这一点:“如果您**将闭包分配给类实例的属性*,也会发生强引用循环* *,并且该闭包的主体捕获了该实例。”。此处的示例代码不保留对闭包的引用,因此没有强引用循环 (2认同)