Blocks on Swift (animateWithDuration:animations:completion:)

manolosavi picture manolosavi · Jun 6, 2014 · Viewed 86.4k times · Source

I'm having trouble making the blocks work on Swift. Here's an example that worked (without completion block):

UIView.animateWithDuration(0.07) {
    self.someButton.alpha = 1
}

or alternatively without the trailing closure:

UIView.animateWithDuration(0.2, animations: {
    self.someButton.alpha = 1
})

but once I try to add the completion block it just won't work:

UIView.animateWithDuration(0.2, animations: {
    self.blurBg.alpha = 1
}, completion: {
    self.blurBg.hidden = true
})

The autocomplete gives me completion: ((Bool) -> Void)? but not sure how to make it work. Also tried with trailing closure but got the same error:

! Could not find an overload for 'animateWithDuration that accepts the supplied arguments

Update for Swift 3 / 4:

// This is how I do regular animation blocks
UIView.animate(withDuration: 0.2) {
    <#code#>
}

// Or with a completion block
UIView.animate(withDuration: 0.2, animations: {
    <#code#>
}, completion: { _ in
    <#code#>
})

I don't use the trailing closure for the completion block because I think it lacks clarity, but if you like it then you can see Trevor's answer below.

Answer

Zaksoup picture Zaksoup · Jun 6, 2014

the completion parameter in animateWithDuration takes a block which takes one boolean parameter. In swift, like in Obj C blocks, you must specify the parameters that a closure takes:

UIView.animateWithDuration(0.2, animations: {
    self.blurBg.alpha = 1
}, completion: {
    (value: Bool) in
    self.blurBg.hidden = true
})

The important part here is the (value: Bool) in. That tells the compiler that this closure takes a Bool labeled 'value' and returns void.

For reference, if you wanted to write a closure that returned a bool the syntax would be

{(value: Bool) -> bool in
    //your stuff
}