Swift 在闭包中引用属性需要显式';赛尔夫';使捕获语义显式
尝试将HTML从web服务加载到webview时,出现以下错误: 闭包中对属性“webviewHTML”的引用需要显式的“self”。才能使捕获语义显式 这意味着什么,如何将HTML字符串加载到web视图中Swift 在闭包中引用属性需要显式';赛尔夫';使捕获语义显式,swift,swift2,Swift,Swift2,尝试将HTML从web服务加载到webview时,出现以下错误: 闭包中对属性“webviewHTML”的引用需要显式的“self”。才能使捕获语义显式 这意味着什么,如何将HTML字符串加载到web视图中 func post(url: String, params: String) { let url = NSURL(string: url) let params = String(params); let request = NSMutableURLRequest(
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();
}
使用
self
是明确确认引用(也称为捕获)闭包中的构造(类/结构/枚举),这意味着在解除分配所述闭包之前不会解除分配self
仔细想想,
self
可以很好地推断出来(实际上,在闭包之外使用webviewHTML
时),但不推断它是一个有意的设计决策,因为Swift是一种安全第一语言在回答这个问题之前,您必须知道内存周期是什么。看
现在您知道了什么是内存周期: 这个错误是我告诉你的 “嘿,NSURLSession闭包正试图保留webviewHTML 堆和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();
}
有关详细信息,请参见此非常好的答案,谢谢您-现在这更有意义了。您通常做的是:将
数据、响应、错误更改为:[弱自我]数据、响应、,在
中出错,然后在闭包中取消对self
的引用,而不是取消对它的引用self?
,因为self
现在被设置为nil
(又称为nullable
),因此您必须取消对它的引用这里有一些微妙之处。斯坦福课程的视频使用[弱自我]来防止视图保留在堆上,作为不删除引用循环的一种精确方法。只有当闭包引用self并self保留对闭包的引用时,才会发生循环(这在Apple文档中有明确说明:“如果将闭包分配给类实例的属性,并且闭包的主体捕获该实例,也会发生强引用循环。”。此处的示例代码没有保留对闭包的引用,因此没有强引用cycle@Dale谢谢你的评论。这里的示例代码没有保留对闭包的引用,因此没有强引用循环。这是什么意思?实例本身没有对post
函数的强引用吗?因此,对于任务
?@Honey,变量task和request都是函数post()中的本地变量。一旦post退出,即使NSURLSession将继续异步执行,这些变量也将被释放。您可以在调用post()后在代码中设置断点来确认此行为在闭包中。在执行闭包之前,您应该看到post exit返回到调用方。也许,但这降低了抽象级别,降低了语言的规则性。此外,由于使用了引用计数,因此更安全。