Обозреватель didSet не вызывается при инициализации свойства - PullRequest
1 голос
/ 07 марта 2019

Учитывая следующий класс,

class Spaceship {

    var position: CGPoint! {
        didSet {
            node.position = position
        }
    }

    var node: SKSpriteNode!

    init(frame: CGRect) {

        node = SKSpriteNode(
            color: UIColor.red,
            size: CGSize(
                width: frame.size.width / 5,
                height: frame.size.width / 5
            )
        )

        self.position = CGPoint(x: frame.midX, y: frame.midY)

    } 

}

похоже, что didSet наблюдатель свойства position не вызывается.

Поскольку наблюдатель didSet должен установить положение узла SpriteKit при изменении свойства position, я подумал, что вместо использования той же строки кода, содержащейся в блоке didSet, я мог бы вместо этого запустить последний, но это не похоже на работу; когда сцена создается (в основном GameScene, который просто создает Spaceship объекты и добавляет spaceship.node к дочерним узлам сцены), позиция node выглядит как 0; 0.

Любая подсказка, почему это происходит? Спасибо.

Обновление: хотя оператор defer работает, назначение не позволяет использовать его.

Ответы [ 3 ]

3 голосов
/ 07 марта 2019

Вместо того, чтобы использовать didSet для обновления вашего узла, напрямую перенаправляйте запросы на него:

class Spaceship {

    let node: SKSpriteNode

    init(frame: CGRect) {
        self.node = SKSpriteNode(
            color: UIColor.red,
            size: CGSize(
                width: frame.size.width / 5,
                height: frame.size.width / 5
            )
        )

        self.position = CGPoint(x: frame.midX, y: frame.midY)
    }

    var position: CGPoint {
        get { return node.position }
        set { node.position = newValue }
    }
}
1 голос
/ 07 марта 2019

Наблюдатели willSet и didSet свойств суперкласса вызываются, когда свойство устанавливается в инициализаторе подкласса, после вызова инициализатора суперкласса. Они не вызываются, пока класс устанавливает свои собственные свойства до вызова инициализатора суперкласса.

Одним из возможных решений может быть установка свойства position вне инициализатора Spaceship или установка непосредственно позиции node.

0 голосов
/ 08 марта 2019

Лично я бы просто подкласс космического корабля в качестве SKSpriteNode.Космический корабль, похоже, не является сложным объектом, который включает в себя композицию, а не наследование.

class Spaceship : SKSpriteNode {
    convenience init(frame: CGRect) {
        self.init(
            color: UIColor.red,
            size: CGSize(
                width: frame.size.width / 5, 
                height: frame.size.width / 5
            )
        )
        self.position = CGPoint(x: frame.midX, y: frame.midY)
   } 
}

Теперь я не уверен, почему вы переходите в такой кадр… Я предполагаю, что кадр - это ваша сцена?Если это так, то вы столкнетесь с проблемами, когда точка привязки не равна (0,0).

...