问题
苹果的文件明确指出:
当属性第一次初始化时,不会调用willSet和didSet观察器。只有当属性的值在初始化上下文之外设置时才会调用它们。
是否有可能在初始化期间强制调用这些?
Why?
假设我有这样一个类
class SomeClass {
var someProperty: AnyObject {
didSet {
doStuff()
}
}
init(someProperty: AnyObject) {
self.someProperty = someProperty
doStuff()
}
func doStuff() {
// do stuff now that someProperty is set
}
}
我创建了方法doStuff,以使处理调用更简洁,但我宁愿只处理didSet函数中的属性。有没有办法在初始化期间强制调用这个?
更新
我决定删除类的方便初始化器,并强制您在初始化后设置属性。这让我知道didSet总是会被调用。我还没有决定这是否是更好的整体,但它很适合我的情况。
如果你在初始化式中使用defer,用于更新任何可选属性或进一步更新你已经初始化的非可选属性,并且在你调用了任何super.init()方法之后,那么你的willSet, didSet等将被调用。我发现这比实现单独的方法更方便,你必须在正确的地方跟踪调用。
例如:
public class MyNewType: NSObject {
public var myRequiredField:Int
public var myOptionalField:Float? {
willSet {
if let newValue = newValue {
print("I'm going to change to \(newValue)")
}
}
didSet {
if let myOptionalField = self.myOptionalField {
print("Now I'm \(myOptionalField)")
}
}
}
override public init() {
self.myRequiredField = 1
super.init()
// Non-defered
self.myOptionalField = 6.28
// Defered
defer {
self.myOptionalField = 3.14
}
}
}
将收益率:
I'm going to change to 3.14
Now I'm 3.14
如果你在初始化式中使用defer,用于更新任何可选属性或进一步更新你已经初始化的非可选属性,并且在你调用了任何super.init()方法之后,那么你的willSet, didSet等将被调用。我发现这比实现单独的方法更方便,你必须在正确的地方跟踪调用。
例如:
public class MyNewType: NSObject {
public var myRequiredField:Int
public var myOptionalField:Float? {
willSet {
if let newValue = newValue {
print("I'm going to change to \(newValue)")
}
}
didSet {
if let myOptionalField = self.myOptionalField {
print("Now I'm \(myOptionalField)")
}
}
}
override public init() {
self.myRequiredField = 1
super.init()
// Non-defered
self.myOptionalField = 6.28
// Defered
defer {
self.myOptionalField = 3.14
}
}
}
将收益率:
I'm going to change to 3.14
Now I'm 3.14
不幸的是,根类初始化时不会调用didSet观察器。
如果你的类不是子类,你必须使用getter和setter来实现你想要的功能:
class SomeClass {
private var _test: Int = 0
var test: Int {
get { _test }
set { _test = newValue }
}
init(test: Int) { self.test = test }
}
或者,如果你的类是一个子类,你可以使用didSet并执行:
override init(test: int) {
super.init()
self.test = test
}
在super.init()被调用之后,didSet应该被调用。
有一件事我没有尝试过,但可能也有用:
init(test: int) {
defer { self.test = test }
}
注意:你需要让你的属性为空,或者为它们设置一个默认值,或者打开类属性。