How to Pass Arguments into a Function with Completion Swift

How to pass arguments into a function with completion swift

Your function 'apiRequest' has 2 parameters:

  1. search: String (this parameter expects a String)
  2. completion: @escaping (Result) -> ()

So when you call this method, you will pass these 2 parameters as well, like this:

.onTapGesture {
API().apiRequest(search: "String you want to pass", completion: { (result) in
self.result = result
})
}

Learn about closures, as this completion parameter is also a type of closure (escaping closure).

Pass function to completion handler

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
})

How to call function with completion handler and parameters

Use like this:

func downloadRepositories(parameter1: String, parameter2: String, completed: @escaping () -> ()) {

let parameters: Parameters = [ "parameterA": parameter, "parameterB": parameter2 ]

Alamofire.request(url, parameters: parameters).responseJSON {
//response
completed()
}

Swift: How to pass in a closure as a function argument

OOPS nevermind...

public func queryAllFlightsWithClosure(completionHandler : (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void ) {

took out the {} and it seems to work?

How could I create a function with a completion handler in Swift?

Say you have a download function to download a file from network, and want to be notified when download task has finished.

typealias CompletionHandler = (success:Bool) -> Void

func downloadFileFromURL(url: NSURL,completionHandler: CompletionHandler) {

// download code.

let flag = true // true if download succeed,false otherwise

completionHandler(success: flag)
}

// How to use it.

downloadFileFromURL(NSURL(string: "url_str")!, { (success) -> Void in

// When download completes,control flow goes here.
if success {
// download success
} else {
// download fail
}
})

Hope it helps.

Functions completion handler Swift 4

Declare it like this:

completion: @escaping ((User?, Error?) -> Void)

Inside your function:

completion(user, nil) // when you have user

completion(nil, error) // when you have error

On the completion block call:

completion: { user, error in

if let error = error {
// handle error
}

if let user = user {
// handle user
}
}

how to pass function in parameter using closure in swift 5

You first need to create an extension for UIViewController instead of UIAlertController

Also, set the correct closure argument for the function and then call the function like this.

extension UIViewController {

func action(message: String, firstTitle: String, secondTitle: String, firstAction: (() -> Void)? = nil, secondAction: (() -> Void)? = nil) {

let actionSheet = UIAlertController(title: "", message: message, preferredStyle: .actionSheet)

let eButton = UIAlertAction(title: firstTitle ,
style: .default,
handler: {_ in firstAction?()})

let allEButton = UIAlertAction(title: secondTitle,
style: .default ,
handler: {_ in secondAction?()})

let cancelAction = UIAlertAction(title: "Cancel",
style: .cancel,
handler: nil)


[eButton, allEButton, cancelAction].forEach { $0.setValue(UIColor.red, forKey: "titleTextColor")}


actionSheet.addAction(eButton)
actionSheet.addAction(allEButton)
actionSheet.addAction(cancelAction)

present(actionSheet, animated: true, completion: nil)
}
}

Usage

private extension viewControllerA {
func alertBottomSheat() {
self.action(message: "Update", firstTitle: "Update only", secondTitle: "Update All", firstAction: saveEvent, secondAction: saveEvent)
}

@IBAction func deleteEventButtonClicked(_ sender: Any) {
self.action(message: "delete ", firstTitle: "Delete only", secondTitle: "Delete All ", firstAction: { self.deleteEvent()}, secondAction: { self.deleteEvent(deleteAll: true) })

}

func saveEvent() {

}

func deleteEvent(deleteAll: Bool = false) {

}
}

Note: Fixed coding standard rule and var names.

Swift optional completion handler

Completion handlers are similar to function return values, but not the same. For example, compare the following functions:

/// 1. With return value
func createList(name: String) -> Response { }
/// 2. With completion handler
func createList(name: String, completion: @escaping (Response) -> Void) { }

In the first function, you'd get the return value instantly.

let response = barback.createList(name: name)
if response.status = 200 {
/// trigger some UI component
}

However, if you try the same for the second function, you'll get the Missing argument for parameter 'completion' in call error. That's because, well, you defined a completion: argument label. However, you didn't supply it, as matt commented.

Think of completion handlers as "passing in" a chunk of code into the function, as a parameter. You need to supply that chunk of code. And from within that chunk of code, you can access your Response.

                                           /// pass in chunk of code here
barback.createList(name: name, completion: { response in
/// access `response` from within block of code
if response.status = 200 {
/// trigger some UI component
}
})

Note how you just say barback.createList, not let result = barback.createList. That's because in the second function, with the completion handler, doesn't have a return value (-> Response).

Swift also has a nice feature called trailing closure syntax, which lets you omit the argument label completion:.

barback.createList(name: name) { response in
/// access `response` from within block of code
if response.status = 200 {
/// trigger some UI component
}
}

You can also refer to response, the closure's first argument, by using $0 (which was what I did in my comment). But whether you use $0 or supply a custom name like response is up to you, sometimes $0 is just easier to type out.

barback.createList(name: name) {
/// access $0 (`response`) from within block of code
if $0.status = 200 {
/// trigger some UI component
}
}


Related Topics



Leave a reply



Submit