gpt4 book ai didi

swift - 我应该在计算属性的闭包中使用 weak self 吗?

转载 作者:搜寻专家 更新时间:2023-11-01 05:31:24 24 4
gpt4 key购买 nike

我对在闭包中使用 self 感到困惑。

我们什么时候应该声明 [weak self] ?我理解的一个明显案例是

class Foo{

var closure: ( Void -> Void )?
var x = 0

func doSomething(){
closure = { [weak self] in
if let x = self?.x{
println(x)
}
}
}
}

但是,如果我想创建一个计算属性 bar,它有一个闭包,并且将 self 捕获在里面。像这样,

extension Foo{

var bar: Bar{
let bar = Bar()
bar.completionHandler = {
println(self.x)
}
return bar
}
}

我应该在闭包中使用 [weak self] 吗?

最佳答案

考虑:

extension Foo {
var bar: Bar {
let bar = Bar()
bar.completionHandler = {
print(self.x)
}
return bar
}
}

Should I use [weak self] inside this closure?

通常当人们问这个问题时,真正关心的是“我需要 [weak self] 吗?”避免强引用循环?”答案是,不,这里没有强引用循环。

如果bar是存储的属性,缺少 [weak self]会升起危险信号。如果我们有 Foo 就很容易出问题存储了对 Bar 的引用它本身有一个关闭 self引用回原文Foo .但是有了这个计算属性,Foo没有对 bar 的强引用, 因此强引用循环问题在很大程度上减少了。

话虽如此,我很难想象我不想使用 [weak self] 的地方.如果bar有一个 completionHandler ,这意味着它很可能用于一些异步场景,问题是Foo是否在此过程中需要保留。

所以,真正的问题是“应该”使用 [weak self]归结为什么Bar是,以及它是否对 Foo 拥有任何合理的所有权主张.

让我们试着想出一个实际的例子。 (以下内容有点做作,因为我很难为这种模式想象一个好的用例,但请耐心等待。)

例如,假设 Foo是一个Person对象和 Bar是一些URLSessionTask对于图片下载任务:

class Person {
let name: String
private(set) var image: UIImage?

...
}

extension Person {
var imageTask: URLSessionTask {
let url = ...
return session.dataTask(with: url) { [weak self] data, _, _ in
guard let data = data, let image = UIImage(data: data) else { return }

self?.image = image
}
}
}

所以 Controller 可能会说

let person = Person(...)
let task = person.imageTask
task.resume()

在上面的例子中,我碰巧使用了[weak self]imageTask关闭,不是因为我担心任何强引用循环,而只是因为网络任务通常没有业务要求对模型对象的强引用。 (然后,我也不会亲自将网络接口(interface)埋在模型对象中。)但是在这个例子中,可以省略 [weak self]。这个闭包的引用,例如,如果你想确保 Person对象一直保留到网络请求完成(例如,您可能想将网络请求的结果保存在某个本地持久存储中)。

说了这么多,我真的很难想象我会在哪里使用上述模式。但最重要的是这里没有强引用循环,所以理论上你可以省略 [weak self]不用担心。但在大多数实际情况下,您通常最终会使用 [weak self] .

关于swift - 我应该在计算属性的闭包中使用 weak self 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31487829/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com