gpt4 book ai didi

swift - 什么时候调用计算属性的修改方法,它做什么?

转载 作者:可可西里 更新时间:2023-11-01 00:54:06 24 4
gpt4 key购买 nike

考虑下面的类定义

class Class1 {
var property: String {
get {
return ""
}
set {
print("set called")
}
}
}

如果在 get block 内添加断点并读取 property,执行将暂停,您会观察到调用堆栈中最顶层的方法是 Class1.property.getter

同样,如果您在 set block 内添加断点并设置 property,执行将暂停,您会观察到调用堆栈中最顶层的方法是 Class1.property.setter

在调试崩溃时,我观察到调用堆栈中最顶层的方法是 ClassName.computedPropertyName.modify,其中 ClassNamecomputedPropertyName 是占位符。

谁能指出 modify 方法的作用以及调用时间?

最佳答案

getset 一样,modify 是访问器。这是迈向 generalised accessors 的一部分,并用于使用 yield-once 协程获取对基础值的可变引用。

您实际上可以使用 _modify 关键字在当今的 Swift 中编写 modify 访问器。不过请注意,它还不是官方功能,因此任何明确依赖于 _modifyyield 的代码都可能会被破坏,恕不另行通知。

class C {
var _property: String = ""
var property: String {
get {
return _property
}
_modify {
yield &_property
}
}
}

let c = C()
c.property += "hello"
print(c.property) // hello

在改变 c.property 时,调用 _modify 访问器以获得对某些底层存储的可变引用。 yield 关键字用于通过引用 _property 的存储将控制权转移回调用方。此时,调用者可以对存储应用任意突变,在本例中调用 +=。突变完成后,控制权将转移回 _modify,此时它会返回。

为什么 modify 访问器有用?

简单地说,它避免了值的复制,这可能会触发写入时复制类型的昂贵复制操作,例如 StringArray字典(我讲这个 in more detail here )。通过 modify 访问器改变 c.property 允许字符串就地改变,而不是改变一个临时副本然后写回。

modify为什么要使用协程?

协程的使用允许将可变引用暂时交还给调用者,之后访问者可以执行其他逻辑。

例如:

class C {
var _property: String = ""
var property: String {
get {
return _property
}
_modify {
yield &_property
_property += " world!"
}
}
}

let c = C()
c.property += "hello"
print(c.property) // hello world!

首先让调用者执行它的突变,然后将 "world!" 附加到字符串的末尾。

为什么 modify 访问器出现在您的代码中?

Swift 编译器可以为可变属性隐式合成一个modify 访问器。对于具有 getter 和 setter 的计算属性,实现如下所示:

class Class1 {
var property: String {
get {
return ""
}
set {
print("set called")
}
// What the compiler synthesises:
_modify {
var tmp = property.get() // Made up syntax.
yield &tmp
property.set(tmp)
}
}
}

首先调用 getter 以获得值的可变副本,然后将对该可变副本的引用传递回调用者,然后使用新值调用 setter。

modify 访问器主要用于这种情况,以便通过动态调度实现属性的高效突变。考虑以下示例:

class C {
var property = "hello" {
// What the compiler synthesises:
_modify {
yield &property
}
}
}

class D : C {
override var property: String {
get { return "goodbye" }
set { print(newValue) }
// What the compiler synthesises:
_modify {
var tmp = property.get()
yield &tmp
property.set(tmp)
}
}
}

func mutateProperty(_ c: C) {
c.property += "foo"
}

在改变 c.property 时,modify 访问器被动态调度到。如果这是 C 的实例,这允许将对 property 的存储的引用直接返回给调用者,从而实现高效的就地突变。如果这是 D 的实例,则调用 modify 与调用 getter 后跟 setter 具有相同的效果。

为什么 modify 显示为崩溃堆栈跟踪中最顶层的调用?

我假设这是因为编译器已将您的 getter 和 setter 的实现内联到 modify 访问器中,因此这意味着崩溃可能是由 getter 或 setter 的实现引起的您的属性(property)。

关于swift - 什么时候调用计算属性的修改方法,它做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56426696/

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