考虑以下类定义
class Class1 {
var property: String {
get {
return ""
}
set {
print("set called")
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您在 get 块和 read 中添加断点property,执行将暂停,并且您会观察到调用堆栈中最顶层的方法是Class1.property.getter
类似地,如果您在 set 块内添加断点并 set property,执行将暂停,并且您会观察到调用堆栈中最顶层的方法是Class1.property.setter
在调试崩溃时,我观察到调用堆栈中最顶层的方法是ClassName.computedPropertyName.modifywhereClassName和computedPropertyName是占位符。
谁能指出该modify方法的作用以及何时调用它?
get与和一样set,modify是一个访问器。它是走向通用访问器的一部分,用于使用yield-once协程获取对基础值的可变引用。
实际上,您可以modify在今天的 Swift 中使用_modify关键字编写访问器。但请注意,它还不是正式功能,因此任何明确依赖于该功能的代码都_modify可能yield会在没有通知的情况下被破坏。
class C {
var _property: String = ""
var property: String {
get {
return _property
}
_modify {
yield &_property
}
}
}
let c = C()
c.property += "hello"
print(c.property) // hello
Run Code Online (Sandbox Code Playgroud)
在 mutating 时c.property,_modify调用访问器来获取对某些底层存储的可变引用。使用该yield关键字是为了通过对_property的存储的引用将控制权转移回调用者。此时,调用者可以对存储应用任意突变,在本例中调用+=. 一旦突变完成,控制权就会转移回_modify,此时它会返回。
modify访问器有用?String简而言之,它避免了值的复制,这可能会触发诸如、Array、 和 等写时复制类型的昂贵的复制操作(我在这里更详细地Dictionary讨论这一点)。通过访问器进行变异允许就地改变字符串,而不是改变然后写回的临时副本。c.propertymodify
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!
Run Code Online (Sandbox Code Playgroud)
它首先让调用者执行其突变,然后附加" 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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先调用 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"
}
Run Code Online (Sandbox Code Playgroud)
在 mutating 上c.property,modify访问器被动态分派到。如果这是 的实例C,则允许将 的存储引用property直接返回给调用者,从而实现有效的就地突变。如果这是 的实例D,则调用modifyjust 与调用 getter 和 setter 具有相同的效果。
modify显示为崩溃堆栈跟踪中最顶层的调用?我认为这是因为编译器已将 getter 和 setter 的实现内联到访问器中modify,因此意味着崩溃可能是由属性的 getter 或 setter 的实现引起的。
| 归档时间: |
|
| 查看次数: |
770 次 |
| 最近记录: |