vrwim
vrwim

Reputation: 14310

Pass Int by value to closure

I have this code:

for var i = 0; i < self.blockViews.count; i++ {
    UIView.animateWithDuration(0.2, animations: {
        // Some animation
        }, completion: {
            completion in
            // i is always blockViews.count as the for loop exits before completion closure is called
            if i == 0 {
                // Some completion handling
            }
    })
}

I am trying to use i inside my closure; is there a way to do this other than assigning it to a let, and then using it (pass by value)?

for var i = 0; i < self.blockViews.count; i++ {
    let copyOfI = i
    UIView.animateWithDuration(0.2, animations: {
        // Some animation
        }, completion: {
            completion in
            if copyOfI == 0 {
                // This works
            }
    })
}

Upvotes: 2

Views: 270

Answers (2)

Antonio
Antonio

Reputation: 72760

Actually there's a way to achieve that, and it's called the capture list: you simply have to list the variables you want to capture as a comma separated list enclosed in square brackets - in your case, it's just [i]:

for var i = 0; i < self.blockViews.count; i++ {
    UIView.animateWithDuration(0.2, animations: {
        // Some animation
        }, completion: {
            [i] completion in
         // ^^^ capture list is here
            // i is always blockViews.count as the for loop exits before completion closure is called
            if i == 0 {
                // Some completion handling
            }
            println(i)
    })
}

Reference: Closure Expression

Old answer

You can enclose the loop code in a closure and pass the index as a closure parameter:

for var i = 0; i < self.blockViews.count; i++ {
    { (index) in
        UIView.animateWithDuration(0.2, animations: {
            // Some animation
            }, completion: {
                completion in
                // i is always blockViews.count as the for loop exits before completion closure is called
                if index == 0 {
                    // Some completion handling
                }
        })
    }(i)
}

Upvotes: 3

Chackle
Chackle

Reputation: 2269

You either have to create a copy using a let (like you have done in your question) or pass it into the closure through the closure's parameters.

Seeing as you're using a UIView.animateWithDuration closure, your best bet is assigning it to a let variable inside your closure.

Upvotes: 1

Related Questions