Vladislav
Vladislav

Reputation: 41

How to mutate variable in array?

I'm trying to receive mutable variable from my array, but something goes wrong. Question in code.

var baloonsArray = NSMutableArray()

override func didMoveToView(view: SKView) {
        var baloon = SKSpriteNode(imageNamed: "baloon") //"Variable "baloon" was never mutated; consider changing to "let" constant"
        baloon.xScale = 0.1
        baloon.yScale = 0.1

        ballonsArray.addObject(baloon)
        addChild(baloon)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    for touch in touches {
        for var baloon in baloonsArray {
            baloon.xScale = 0.2 //Here xcode telling me: "Cannot assign to property: "ballon" is immutable". But i declared him as var. With Objective-C there was no problems. What should i do? 

        }
    }
}

When Im trying to change baloon xScale in touchesBegan function xcode telling me: "Cannot assign to property: "ballon" is immutable". But i declared him as var. With Objective-C there was no problems. What should i do?

Upvotes: 3

Views: 954

Answers (2)

Luca Angeletti
Luca Angeletti

Reputation: 59496

Point 1

In the following code you are defining a variable balloon.

This variable exists until it goes out of scope at the end of the method, just an instant before the }.

override func didMoveToView(view: SKView) {
    var balloon = SKSpriteNode(imageNamed: "baloon") //"Variable "baloon" was never mutated; consider changing to "let" constant"
    balloon.xScale = 0.1
    balloon.yScale = 0.1

    ballonsArray.addObject(balloon)
    addChild(balloon)
}

Now, this variable refers an object of type SKSpriteNode. This means that the variable is a pointer, more specifically it contains a number that is the address of the sprite inside the heap.

If you change some property of the sprite you are not changing the variable, infact the variable balloon still contains the address of the sprite into the heap. So you are not mutating it.

The only way to mutate the variable balloon is assigning it to another SKSpriteNode. You are not doing it so the warning correct.

Point 2

The matt's answer is totally correct.

You could also consider not to use NSMutableArray. The Swift native array is much better and does support generics. So you can avoid a cast.

class Scene : SKScene {

    var ballonsArray = [SKSpriteNode]()

    override func didMoveToView(view: SKView) {
        let balloon = SKSpriteNode(imageNamed: "baloon")
        balloon.xScale = 0.1
        balloon.yScale = 0.1
        ballonsArray.append(balloon)
        addChild(balloon)
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        ballonsArray.map { $0.xScale = 0.2 }
    }
}

Hope this helps.

Upvotes: 1

matt
matt

Reputation: 534925

The problem is your use of NSMutableArray. To Swift, it is opaque. That is, Swift doesn't know what is in it. But Swift has strict typing. So it doesn't know what properties its elements have, and it isn't going to let you assign to a property it doesn't understand. So if you really want to use NSMutableArray, you must cast its elements when you fetch them, so Swift knows what they are:

for baloon in baloonsArray {
    let baloonsprite = baloon as! SKSpriteNode
    baloonsprite.xScale = 0.2
}

That works. However, it would be better not to use NSMutableArray in the first place. Instead, declare baloonsArray as a mutable Swift array:

var baloonsArray = [SKSpriteNode]()

That takes care of the problem in a much neater way. Now Swift knows what is in this array - it is SKSpriteNode objects. And Swift knows that it is okay to assign to an SKSpriteNode's xScale.

You need to get used to Swift's strict typing, including the fact that the elements of an array are typed.

Upvotes: 2

Related Questions