106

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.

Community
  • 1
  • 1
manolosavi
  • 1,113
  • 2
  • 7
  • 10
  • 1
    "The autocomplete gives me completion: ((Bool) -> Void)? but not sure how to make it work" Exactly what it says. This must be a block that takes a Bool and returns a Void. – matt Jun 05 '14 at 22:50
  • How do you know what the ((Bool) -> Void)? is for? Since I've used this in ObjC before I know it is BOOL finished. But how would a swift coder know? – malhal Oct 04 '14 at 15:24

7 Answers7

206

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
}
aheze
  • 24,434
  • 8
  • 68
  • 125
Zaksoup
  • 2,200
  • 1
  • 12
  • 4
41

The completion is correct, the closure must accept a Bool parameter: (Bool) -> (). Try

UIView.animate(withDuration: 0.2, animations: {
    self.blurBg.alpha = 1
}, completion: { finished in
    self.blurBg.hidden = true
})
Karen Hovhannisyan
  • 1,140
  • 2
  • 21
  • 31
Nicholas H.
  • 1,321
  • 13
  • 26
  • 2
    It's worth noting that this version *is* correct. You don't need to write out the full type since it can be inferred, so all you need is just to mention the closure parameter as mentioned here. – Chuck Jun 05 '14 at 22:49
32

Underscore by itself alongside the in keyword will ignore the input

Swift 2

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

Swift 3, 4, 5

UIView.animate(withDuration: 0.2, animations: {
    self.blurBg.alpha = 1
}, completion: { _ in
    self.blurBg.isHidden = true
})
Karen Hovhannisyan
  • 1,140
  • 2
  • 21
  • 31
Dan Greenfield
  • 341
  • 2
  • 5
10

There is my solution above based on accepted answer above. It fades out a view and hiddes it once almost invisible.

Swift 2

func animateOut(view:UIView) {

    UIView.animateWithDuration (0.25, delay: 0.0, options: UIViewAnimationOptions.CurveLinear ,animations: {
        view.layer.opacity = 0.1
        }, completion: { _ in
            view.hidden = true
    })   
}

Swift 3, 4, 5

func animateOut(view: UIView) {

    UIView.animate(withDuration: 0.25, delay: 0.0, options: UIView.AnimationOptions.curveLinear ,animations: {
        view.layer.opacity = 0.1
    }, completion: { _ in
        view.isHidden = true
    })
}
Karen Hovhannisyan
  • 1,140
  • 2
  • 21
  • 31
Jaro
  • 3,799
  • 5
  • 31
  • 47
4

Here you go, this will compile

Swift 2

UIView.animateWithDuration(0.3, animations: {
    self.blurBg.alpha = 1
}, completion: {(_) -> Void in
    self.blurBg.hidden = true
})

Swift 3, 4, 5

UIView.animate(withDuration: 0.3, animations: {
    self.blurBg.alpha = 1
}, completion: {(_) -> Void in
    self.blurBg.isHidden = true
})

The reason I made the Bool area an underscore is because you not using that value, if you need it you can replace the (_) with (value : Bool)

Karen Hovhannisyan
  • 1,140
  • 2
  • 21
  • 31
Kris Gellci
  • 9,539
  • 6
  • 40
  • 47
2

Sometimes you want to throw this in a variable to animate in different ways depending on the situation. For that you need

 let completionBlock : (Bool) -> () = { _ in 
 }

Or you could use the equally verbose:

 let completionBlock = { (_:Bool) in 
 }

But in any case, you have have to indicate the Bool somewhere.

Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421
0

SWIFT 3.x + 4.x

I'd like to make an update and simplify the things.

Example below is implemented in any view it is hiding slowly and when it is completely transparent; removes it self from parent view

ok variable will always returns true with animation termination.

    alpha = 1
    UIView.animate(withDuration: 0.5, animations: {
        self.alpha = 0
    }) { (ok) in
        print("Ended \(ok)")
        self.removeFromSuperview()
    }
Trevor
  • 1,051
  • 12
  • 16