gpt4 book ai didi

swift - 为什么闭包捕获引用而函数不捕获引用?另外,为什么闭包声明需要 "lazy"关键字?

转载 作者:行者123 更新时间:2023-11-30 10:49:45 25 4
gpt4 key购买 nike

我在 Xcode Playground 中使用以下代码进行了实验:

class X {

var a = 3

init(a: Int) {
self.a = a
}

deinit {
print("\(self.a) is deallocated.")
}

func returnX() -> Int {
return self.a
}

lazy var anotherReturnX: () -> Int = {
return self.a
}
}

var e: X? = X(a: 6)
print(e!.returnX())
e = nil // prints "6 is deallocated."

var f: X? = X(a: 7)
print(f!.anotherReturnX())
f = nil // prints nothing

从上面的代码中,我可以看到函数 returnX() 中没有捕获任何引用。 ,因此e一旦我设置 e 就被释放至nil 。但是,在闭包 anotherReturnX() 中捕获了引用。 ,因此f没有被解除分配。显然,这意味着闭包捕获引用,而函数则不捕获引用。

此外,当我第一次输入代码时,我没有包含 lazy闭包声明之前的关键字,因为我认为没有必要这样做。但是它会触发编译时错误。我推断,由于闭包只能在实例化后访问,因此它必须访问实例化的 self 。但由于我在这里声明的实际上是一个“匿名函数”,为什么闭包会访问 self无论如何在实例化期间?

经过一番思考,我发现了更多的矛盾。例如,我知道调用闭包时会捕获引用。但是,在 X 初始化期间,我只是分配一个闭包给变量而不调用它,与其他实例属性的声明相同。因此,闭包在初始化期间不应该执行任何操作,并且在没有关键字 lazy 的情况下编译代码。应该没事。但是编译失败。我不确定我的理解出了什么问题。

我读过一些相关文章,例如强/弱引用、保留周期、惰性存储属性。然而,许多人解释“发生了什么”,却没有过多谈论“为什么”。

那么除了标题中提出的问题之外,我还想澄清一下,是什么让函数和闭包彼此不同,以至于出现上述情况?

更新:

闭包捕获引用而函数不捕获引用的事实进一步“强制”在我身上,因为根据 Xcode 编译器,我可以重写 return self.areturn areturnX() ,但我不能在 anotherReturnX 中这样做。因此,我想我必须接受这一点,尽管函数和闭包很相似,因为它们都是“功能包”,但函数与闭包不同,它不捕获引用。如果深究其原因的话,可能会涉及到 Swift 本身的设计?

但是,我还是不明白为什么lazy闭包声明需要关键字。

最佳答案

lazy var anotherReturnX: () -> Int = {
return self.a
}

这里的 self 是一个坚强的 self 。当一个对象强引用另一个对象时,ARC 无法释放,因此会创建一个保留循环。该引用应该是弱的,以避免通过在 block 内创建弱 self 来避免保留循环。

lazy var anotherReturnX: () -> Int = { [weak self] in
return self?.a
}

关于swift - 为什么闭包捕获引用而函数不捕获引用?另外,为什么闭包声明需要 "lazy"关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54881825/

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