是否有可能允许didSet在初始化过程中调用Swift?

苹果的文档指出:

当一个属性第一次初始化时,willSet和didSet观察者不会被调用。 只有当属性值设置在初始化上下文之外时,才会调用它们。

在初始化过程中是否可以强制这些被调用?

为什么?

比方说,我有这个class

class SomeClass { var someProperty: AnyObject { didSet { doStuff() } } init(someProperty: AnyObject) { self.someProperty = someProperty doStuff() } func doStuff() { // do stuff now that someProperty is set } } 

我创build了方法doStuff ,使处理调用更简洁,但我宁愿只是在didSet函数内处理属性。 有没有办法强制这个在初始化过程中调用?

更新

我决定删除我的类的方便初始化程序,并强制您在初始化后设置属性。 这让我知道didSet总是会被调用。 我还没有决定这是否更好,但它适合我的情况。

创build一个自己的set-Method并在init-Method中使用它:

 class SomeClass { var someProperty: AnyObject! { didSet { //do some Stuff } } init(someProperty: AnyObject) { setSomeProperty(someProperty) } func setSomeProperty(newValue:AnyObject) { self.someProperty = newValue } } 

如果在初始化程序中使用延迟,为了更新任何可选属性或进一步更新已经初始化的非可选属性,并且在调用任何超级初始化方法之后,将调用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 

作为奥利弗答案的一个变种,你可以将这些行包装在一个闭包中。 例如:

 class Classy { var foo: Int! { didSet { doStuff() } } init( foo: Int ) { // closure invokes didSet ({ self.foo = foo })() } } 

编辑:布赖恩韦斯特法尔的答案是更好的恕我直言。 关于他的好处是暗示了他的意图。

我有同样的问题,这对我的作品

 class SomeClass { var someProperty: AnyObject { didSet { doStuff() } } init(someProperty: AnyObject) { defer { self.someProperty = someProperty } } func doStuff() { // do stuff now that someProperty is set } } 

如果你在一个子类中这样做,这是有效的

 class Base { var someProperty: AnyObject { didSet { doStuff() } } required init() { someProperty = "hello" } func doStuff() { print(someProperty) } } class SomeClass: Base { required init() { super.init() someProperty = "hello" } } let a = Base() let b = SomeClass() 

a例子中, didSet没有被触发。 但在b例子中, didSet被触发,因为它在子类中。 它必须在initialization context上做些什么,在这种情况下, superclass就是在意这一点

虽然这不是一个解决scheme,但另一种解决方法是使用类构造函数:

 class SomeClass { var someProperty: AnyObject { didSet { // do stuff } } class func createInstance(someProperty: AnyObject) -> SomeClass { let instance = SomeClass() instance.someProperty = someProperty return instance } } 

在特定的情况下,如果你想在你的超类中可用的属性中调用willSetdidSet ,你可以直接指定你的超级属性:

 override init(frame: CGRect) { super.init(frame: frame) // this will call `willSet` and `didSet` someProperty = super.someProperty } 

请注意,具有闭包的查尔斯主义解决scheme在这种情况下总是可以工作的。 所以我的解决scheme只是一个select。

你可以用obj-с方式解决它:

 class SomeClass { private var _someProperty: AnyObject! var someProperty: AnyObject{ get{ return _someProperty } set{ _someProperty = newValue doStuff() } } init(someProperty: AnyObject) { self.someProperty = someProperty doStuff() } func doStuff() { // do stuff now that someProperty is set } } 
Interesting Posts