computed 属性 的 modify 方法何时被调用,它有什么作用?
When is the modify method of a computed property called and what does it do?
考虑以下 class 定义
class Class1 {
var property: String {
get {
return ""
}
set {
print("set called")
}
}
}
如果在 get 块内添加断点并读取 property
,执行将暂停,您会观察到调用堆栈中最顶层的方法是 Class1.property.getter
同样,如果在 set 块内添加断点并设置 property
,执行将暂停,您会观察到调用堆栈中最顶层的方法是 Class1.property.setter
在调试崩溃时,我观察到调用堆栈中最顶层的方法是 ClassName.computedPropertyName.modify
,其中 ClassName
和 computedPropertyName
是占位符。
谁能指出 modify
方法的作用以及调用时间?
只要您更改 属性 的值,就会调用 modify
。因此,对于一个字符串,您可以随时设置、更新或删除该字符串的值。
以下是调用修改的示例。
var string: String? //modify not called here
string = “new string”
string = nil
- 每次赋值时都会调用的代码
- 计算属性始终是变量
get { } :当检索 属性 的值时,将执行此代码块。
set { } : 当设置 a 属性 的值时,这部分代码将被执行。
例子
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
与 get
和 set
一样,modify
是访问器。它是迈向 generalised accessors 的一部分,用于使用 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
在改变 c.property
后,调用 _modify
访问器以获得对某些底层存储的可变引用。 yield
关键字用于通过引用 _property
的存储将控制权转移回调用方。此时,调用者可以对存储应用任意突变,在本例中调用 +=
。突变完成后,控制权将转移回 _modify
,此时它 returns.
为什么 modify
访问器有用?
简单地说,它避免了值的复制,这会触发 copy-on-write 类型的昂贵复制操作,例如 String
、Array
和 Dictionary
(我谈谈这个 )。通过 modify
访问器改变 c.property
允许改变字符串 in-place,而不是改变一个临时副本然后写回。
为什么 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
的存储的引用直接返回给调用者,从而允许有效的 in-place 突变。如果这是 D
的一个实例,那么调用 modify
与调用 getter 后跟 setter.
的效果相同
为什么 modify
在崩溃的堆栈跟踪中显示为最顶层的调用?
我假设这是因为编译器已将 getter 和 setter 的实现内联到 modify
访问器中,因此这意味着崩溃可能是由实施 属性.
的 getter 或 setter
考虑以下 class 定义
class Class1 {
var property: String {
get {
return ""
}
set {
print("set called")
}
}
}
如果在 get 块内添加断点并读取 property
,执行将暂停,您会观察到调用堆栈中最顶层的方法是 Class1.property.getter
同样,如果在 set 块内添加断点并设置 property
,执行将暂停,您会观察到调用堆栈中最顶层的方法是 Class1.property.setter
在调试崩溃时,我观察到调用堆栈中最顶层的方法是 ClassName.computedPropertyName.modify
,其中 ClassName
和 computedPropertyName
是占位符。
谁能指出 modify
方法的作用以及调用时间?
modify
。因此,对于一个字符串,您可以随时设置、更新或删除该字符串的值。
以下是调用修改的示例。
var string: String? //modify not called here
string = “new string”
string = nil
- 每次赋值时都会调用的代码
- 计算属性始终是变量
get { } :当检索 属性 的值时,将执行此代码块。
set { } : 当设置 a 属性 的值时,这部分代码将被执行。
例子
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
与 get
和 set
一样,modify
是访问器。它是迈向 generalised accessors 的一部分,用于使用 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
在改变 c.property
后,调用 _modify
访问器以获得对某些底层存储的可变引用。 yield
关键字用于通过引用 _property
的存储将控制权转移回调用方。此时,调用者可以对存储应用任意突变,在本例中调用 +=
。突变完成后,控制权将转移回 _modify
,此时它 returns.
为什么 modify
访问器有用?
简单地说,它避免了值的复制,这会触发 copy-on-write 类型的昂贵复制操作,例如 String
、Array
和 Dictionary
(我谈谈这个 modify
访问器改变 c.property
允许改变字符串 in-place,而不是改变一个临时副本然后写回。
为什么 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
的存储的引用直接返回给调用者,从而允许有效的 in-place 突变。如果这是 D
的一个实例,那么调用 modify
与调用 getter 后跟 setter.
为什么 modify
在崩溃的堆栈跟踪中显示为最顶层的调用?
我假设这是因为编译器已将 getter 和 setter 的实现内联到 modify
访问器中,因此这意味着崩溃可能是由实施 属性.