deinit 末尾的 Defer 语句会产生警告
Defer statement at the end of deinit produces a warning
因为 Xcode 10.2 (Swift 5) defer
声明在deinit
范围的末尾产生:
'defer' statement before end of scope always executes immediately; replace with 'do' statement to silence this warning
我们来看这个例子:
var foo: String {
didSet {
// smt
}
}
deinit {
defer { <--- Warning
foo = bar
}
}
- 当然可以通过将代码从观察者移动到方法并显式调用它来消除此警告,但是…
这个警告有什么意义? - deinit
中的 defer
语句是否合理? (例如能够触发属性的观察者).
警告是正确的,因为在此处使用 defer
不会更改程序的执行顺序,而这正是该语句的设计目的。然而不幸的是,建议的替换会改变您程序的行为(提交错误:SR-10207)。
值得注意的是,使用 defer
来触发 属性 观察器有点像 hack,它之所以起作用,是因为类型检查器认为它是与 deinit
body。您也可以使用闭包表达式实现相同的结果:
deinit {
{ foo = bar }()
}
理想情况下,会有某种形式的语法可以让您告诉 Swift "don't perform a direct-to-storage access here",这样就不需要这样的解决方法,但目前没有。
一个不那么棘手的解决方法是将所需的反初始化器逻辑提取到一个单独的方法中,该方法将逻辑置于 属性 访问正常完成的上下文中:
class C {
var bar = ""
var foo: String {
didSet {
// smt
}
}
init(foo: String) { self.foo = foo }
private func doDeinit() {
foo = bar
}
deinit {
doDeinit()
}
}
因为 Xcode 10.2 (Swift 5) defer
声明在deinit
范围的末尾产生:
'defer' statement before end of scope always executes immediately; replace with 'do' statement to silence this warning
我们来看这个例子:
var foo: String {
didSet {
// smt
}
}
deinit {
defer { <--- Warning
foo = bar
}
}
- 当然可以通过将代码从观察者移动到方法并显式调用它来消除此警告,但是…
这个警告有什么意义? - deinit
中的 defer
语句是否合理? (例如能够触发属性的观察者).
警告是正确的,因为在此处使用 defer
不会更改程序的执行顺序,而这正是该语句的设计目的。然而不幸的是,建议的替换会改变您程序的行为(提交错误:SR-10207)。
值得注意的是,使用 defer
来触发 属性 观察器有点像 hack,它之所以起作用,是因为类型检查器认为它是与 deinit
body。您也可以使用闭包表达式实现相同的结果:
deinit {
{ foo = bar }()
}
理想情况下,会有某种形式的语法可以让您告诉 Swift "don't perform a direct-to-storage access here",这样就不需要这样的解决方法,但目前没有。
一个不那么棘手的解决方法是将所需的反初始化器逻辑提取到一个单独的方法中,该方法将逻辑置于 属性 访问正常完成的上下文中:
class C {
var bar = ""
var foo: String {
didSet {
// smt
}
}
init(foo: String) { self.foo = foo }
private func doDeinit() {
foo = bar
}
deinit {
doDeinit()
}
}