IT

Swift에서 초기화하는 동안 didSet을 호출 할 수 있습니까?

lottoking 2020. 5. 13. 08:26
반응형

Swift에서 초기화하는 동안 didSet을 호출 할 수 있습니까?


질문

Apple의 문서는 다음을 지정합니다.

속성이 처음 초기화 될 때 willSet 및 didSet 옵저버가 호출되지 않습니다. 속성 값이 초기화 컨텍스트 외부에서 설정된 경우에만 호출됩니다.

초기화 중에 이들을 강제로 호출 할 수 있습니까?

왜?

이 수업이 있다고 가정 해 봅시다

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항상 부름을받을 수 있습니다. 이것이 전체적으로 더 좋은지 결정하지는 않았지만 내 상황에 잘 맞습니다.


자체 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
    }
}

당신이 사용하는 경우 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

As a variation of Oliver's answer, you could wrap the lines in a closure. Eg:

class Classy {

    var foo: Int! { didSet { doStuff() } }

    init( foo: Int ) {
        // closure invokes didSet
        ({ self.foo = foo })()
    }

}

Edit: Brian Westphal's answer is nicer imho. The nice thing about his is that it hints at the intent.


I had the same problem and this works for me

class SomeClass {
    var someProperty: AnyObject {
        didSet {
            doStuff()
        }
    }

    init(someProperty: AnyObject) {
        defer { self.someProperty = someProperty }
    }

    func doStuff() {
        // do stuff now that someProperty is set
    }
}

This works if you do this in a subclass

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()

In a example, didSet is not triggered. But in b example, didSet is triggered, because it is in the subclass. It has to do something with what initialization context really means, in this case the superclass did care about that


While this isn't a solution, an alternative way of going about it would be using a class constructor:

class SomeClass {
    var someProperty: AnyObject {
        didSet {
            // do stuff
        }
    }

    class func createInstance(someProperty: AnyObject) -> SomeClass {
        let instance = SomeClass() 
        instance.someProperty = someProperty
        return instance
    }  
}

In the particular case where you want to invoke willSet or didSet inside init for a property available in your superclass, you can simply assign your super property directly:

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

Note that Charlesism solution with a closure would always work too in that case. So my solution is just an alternative.


You can solve it in obj-с way:

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
    }
}

참고URL : https://stackoverflow.com/questions/25230780/is-it-possible-to-allow-didset-to-be-called-during-initialization-in-swift

반응형