简体   繁体   中英

didSet observer does not get called when initialising property

Given the following class,

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)

    } 

}

it looks as though the didSet observer of the position property does not get called.

Since the didSet observer should set the SpriteKit node's position when the position property gets modified, I thought that instead of using the same line of code contained within the didSet block, I could trigger the latter instead, but it doesn't seem to work; when the scene gets created (in the main GameScene, which simply creates a Spaceship objects and adds the spaceship.node to the scene's node children), the node 's position seems to be 0; 0 0; 0 .

Any clue on why does this happen? Thank you.

Update: although the defer statement works, the assignment does not allow to make use of it.

Rather than using didSet to update your node, directly forward queries to it:

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

The willSet and didSet observers of superclass properties are called when a property is set in a subclass initializer, after the superclass initializer has been called. They are not called while a class is setting its own properties , before the superclass initializer has been called.

One possible solution could be to set the position property outside of the Spaceship 's initialiser, or also set directly the node 's position.

I personally would just subclass Spaceship as an SKSpriteNode. Spaceship does not seem to be a complex object that involves composition over inheritance.

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

Now I am not sure why you are passing in frame like this.... I am assuming frame is your scene? If this is the case, you are going to come across issues when anchor point is not (0,0).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM