derekFairholm
derekFairholm

Reputation: 285

Swift for loop not working

I'm baffled by this loop in my Swift code that won't work. Here's the entirety of the function--"pulseChar" is giving me the error "index out of range":

func openingSequence(){
        let nodeList = [self.drum,self.piano,self.guitarBoard]
        let offset = SKAction.waitForDuration(10)
        let stOne = SKAction.runBlock { () -> Void in
            for var i in 0...nodeList.count-1{
                nodeList[i].runAction(SKAction.fadeAlphaTo(0.3, duration: 0.3))
                i++
            }
        }
        let firstLineWait = SKAction.waitForDuration(4)
        let moveSprites = SKAction.runBlock { () -> Void in
            moveScale(self.rheaBoard, duration: 0.5, to: CGPoint(x: 100, y: self.frame.height - 85), size: 0.4)
            moveScale(self.guitarBoard, duration: 0.5, to: CGPoint(x: self.frame.midX - self.frame.midX/2, y: 65), size: 0.35)
            for var i in 0...nodeList.count-1{
                nodeList[i].runAction(fadeI)
                i++
            }
        }
        let fadeAudio = SKAction.runBlock { () -> Void in
            fadeOtherTracksOut([9,8,4,2,1])
        }
        let moveFade = SKAction.group([moveSprites,fadeAudio])
        let pulseChar = SKAction.runBlock { () -> Void in
            for var i in 0...nodeList.count-1{
                self.background.runAction(SKAction.runBlock({ () -> Void in
                    pulse(nodeList[i], startScale: 0.35, endScale: 0.4)
                }))
                i++
            }
            self.startInteaction = true
        }

        background.runAction(SKAction.sequence([offset,stOne,firstLineWait,moveFade,pulseChar]))
    }

My compiler is telling me that i = 3 when it fails...but "i" should not get to three, as

nodeList.count = 3

and I use the range

for var i  in 0...nodeList.count-1

Also, the identical loops before it work just fine...what's going on here? I'm new to programming so if this is a ridiculously simple fix you'll have to excuse me. But help would be greatly appreciated.

EDIT

It seems that the operator i++ needed to be inside the runBlock:

let pulseChar = SKAction.runBlock { () -> Void in
            for var i in 0...nodeList.count-1{
                self.background.runAction(SKAction.runBlock({ () -> Void in
                    pulse(nodeList[i], startScale: 0.35, endScale: 0.4)
                    i++
                }))
            }

This fixes the problem, but I would really appreciate it if someone wouldn't mind explaining why this is the case. It seems to me that if the operator i++ is within the loop it should never == 3.

Upvotes: 2

Views: 2437

Answers (2)

Harshal Bhavsar
Harshal Bhavsar

Reputation: 1673

From swift programming guide provided by apple Check Here For More Details

Care Fully look at the following code and it's output.

for index in 1...5 {
    print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25

In For in loop we do not require to increment the counter. The increment part is handled by the loop it self

Try Following Updated code.

func openingSequence(){
        let nodeList = [self.drum,self.piano,self.guitarBoard]
        let offset = SKAction.waitForDuration(10)
        let stOne = SKAction.runBlock { () -> Void in
            for var i in 0..<nodeList.count{
                nodeList[i].runAction(SKAction.fadeAlphaTo(0.3, duration: 0.3))

            }
        }
        let firstLineWait = SKAction.waitForDuration(4)
        let moveSprites = SKAction.runBlock { () -> Void in
            moveScale(self.rheaBoard, duration: 0.5, to: CGPoint(x: 100, y: self.frame.height - 85), size: 0.4)
            moveScale(self.guitarBoard, duration: 0.5, to: CGPoint(x: self.frame.midX - self.frame.midX/2, y: 65), size: 0.35)
            for var i in 0..<nodeList.count{
                nodeList[i].runAction(fadeI)

            }
        }
        let fadeAudio = SKAction.runBlock { () -> Void in
            fadeOtherTracksOut([9,8,4,2,1])
        }
        let moveFade = SKAction.group([moveSprites,fadeAudio])
        let pulseChar = SKAction.runBlock { () -> Void in
            for var i in 0..<nodeList.count{
                self.background.runAction(SKAction.runBlock({ () -> Void in
                    pulse(nodeList[i], startScale: 0.35, endScale: 0.4)
                }))

            }
            self.startInteaction = true
        }

        background.runAction(SKAction.sequence([offset,stOne,firstLineWait,moveFade,pulseChar]))
    }

Upvotes: 0

vadian
vadian

Reputation: 285069

Don't increment the index variable i "manually", the repeat loop does that automatically.

And you can use the half-open range operator to avoid the extra subtraction, for example

for i in 0..<nodeList.count {
     nodeList[i].runAction(SKAction.fadeAlphaTo(0.3, duration: 0.3))
}

or

for node in nodeList {
     node.runAction(SKAction.fadeAlphaTo(0.3, duration: 0.3))
}

if the numeric index is not needed.

Or even

nodeList.forEach{ $0.runAction(SKAction.fadeAlphaTo(0.3, duration: 0.3)) }

Upvotes: 5

Related Questions