How to pass arguments into a function with completion swift
Your function 'apiRequest' has 2 parameters:
- search: String (this parameter expects a String)
- 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
Does _Arraytype or _Arrayprotocol Not Available in Swift 3.1
Unexpectedly Found Nil While Unwrapping an Optional Value While Reading from Ds with Fromcstring
Get Images from Document Directory Not File Path Swift 3
Swift Nsunknownkeyexception - Setvalue:Forundefinedkey
Nsurlsession Datataskwithrequest Not Being Called
How to Disambiguate a Foreach Loop in Xcode with Swiftui
What Does an Exclamation Mark in a Property in Swift Language
Swift Package Manager Dynamic Library
How to Resume a Published Timer in Swiftui After Navigating to a Different Page
How to Increment Exponentially in Swift
Uicollectionviewcell Not Forcing Cell Size
How to Convert This Date Format in Swift
Why Aren't My Custom Classes Appearing in the Dropdown in Interface Builder
Loading Uiviewcontroller from Instantiateviewcontrollerwithidentifier - Nil Outlets
Why Reloaddata Is Showing Error for My Tableview Inside Viewcontroller