Turnip
Turnip

Reputation: 36632

Pass function to completion handler

I have a function that performs an animation on a view. I would like to implement a completion handler for this function that would be called after the animation is complete.

In ViewController...

hudView.hide(animated: true, myCompletionHandler: {
    // Animation is complete
})

In HudView class...

func hide(animated: Bool, myCompletionHandler: () -> Void) {
    if animated {
        transform = CGAffineTransform(scaleX: 0.7, y: 0.7)

        UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: [], animations: {
            self.alpha = 0
            self.transform = CGAffineTransform.identity
        }, completion: nil) // I want to run 'myCompletionHandler' in this completion handler
    }
}

I've tried a number of things but can't find the correct syntax:

}, completion: myCompletionHandler)

Passing non-escaping parameter 'myCompletionHandler' to function expecting an @escaping closure

}, completion: myCompletionHandler())

Cannot convert value of type 'Void' to expected argument type '((Bool) -> Void)?'

}, completion: { myCompletionHandler() })

Closure use of non-escaping parameter 'myCompletionHandler' may allow it to escape

As a swift novice these error messages don't mean very much to me and I cant seem to find any examples of the correct way to do this.

What is the correct way to pass myCompletionHandler to the .animate completion handler?

Upvotes: 2

Views: 6161

Answers (3)

Arpit Jain
Arpit Jain

Reputation: 1690

You can create your function as,

func hide(_ animated:Bool, completionBlock:((Bool) -> Void)?){

}

And you can call it as,

self.hide(true) { (success) in
   // callback here     
}

Upvotes: 0

David Pasztor
David Pasztor

Reputation: 54706

If you want to pass your own closure as an input argument to UIView.animate, you need to match the types of the closures, so myCompletionHandler has to have a type of ((Bool) -> ())?, just like completion.

func hide(animated: Bool, myCompletionHandler: ((Bool) -> ())?) {
    if animated {
        transform = CGAffineTransform(scaleX: 0.7, y: 0.7)

        UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: [], animations: {
            self.alpha = 0
            self.transform = CGAffineTransform.identity
        }, completion: myCompletionHandler) // I want to run 'myCompletionHandler' in this completion handler
    }
}

This is how you can call it:

hudView.hide(animated: true, myCompletionHandler: { success in
    //animation is complete
})

Upvotes: 8

Damien
Damien

Reputation: 3362

This is how to use completion in UIView.animate :

func hide(animated: Bool, myCompletionHandler: () -> Void) {
    if animated {
        transform = CGAffineTransform(scaleX: 0.7, y: 0.7)

        UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: [], animations: {
            self.alpha = 0
            self.transform = CGAffineTransform.identity
        }, completion: { (success) in
            myCompletionHandler()
        })
    }
}

Upvotes: 0

Related Questions