Closures return value (previously completionBlock)
The plus of closures are, that you can pass everything you want. Methods or functions - it doesn't matter.
You can pass a function within the parameters and just call it.
func someFunctionThatTakesAClosure(completionClosure: () -> ()) {
// function body goes here
if(error = false) {
completionClosure()
}
}
//Call it
someFunctionThatTakesAClosure({
//Completions Stuff
println("someFunctionThatTakesAClosure")
});
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/ch/jEUH0.l
how to use the return value in a completion handler?
You're returning the value into the productToString
function but not doing anything else with it.
func productToString(num: Int,num2: Int,completion: (Int)->String){
let result = num * num2
completion(result) // <--- Your return value ends up here
}
If you want to print the result you have to return it again out of the productToString
function.
func productToString(num: Int,num2: Int,completion: (Int)->String) -> String {
let result = num * num2
return completion(result)
}
Sidenote: The empty brackets that are printed are an empty tuple which is equivalent to Void
in Swift.
Return object for a method inside completion block
If you want the MakeGetRequest
method to return data obtained via dataTaskWithURL
, you can't. That method performs an asynchronous call, which is most likely completed after the MakeGetRequest
has already returned - but more generally it cannot be know in a deterministic way.
Usually asynchronous operations are handled via closures - rather than your method returning the data, you pass a closure to it, accepting the parameters which are returned in your version of the code - from the closure invoked at completion of dataTaskWithURL
, you call that completion handler closure, providing the proper parameters:
class func MakeGetRequest(urlString: String, completionHandler: (data: NSData, error: NSError) -> Void) -> Void
{
let url = NSURL(string: urlString)
var dataResponse: NSData
var err: NSError
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
completionHandler(data: data, error: error)
})
task.resume()
}
Swift 5 update:
class func makeGetRequest(urlString: String, completionHandler: @escaping (Data?, Error?) -> Void) -> Void {
let url = URL(string: urlString)!
var dataResponse: Data
var err: NSError
let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, respone, error) -> Void in
completionHandler(data, error)
})
task.resume()
}
How to use completionHandler Closure with return in Swift?
func getSomething(callback: (Array<AnyObject>) -> ()) {
var dataTask = NSURLSessionDataTask()
dataTask = session.dataTaskWithRequest(request) { (data, response, error) in
if (error == nil) {
var callbackArray = Array<MyObject>()
let responseDict = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as NSDictionary
let response = responseDict.objectForKey("response_key") as NSDictionary
let array = response.objectForKey("array_key") as NSArray
for item: AnyObject in array {
var arrayItem = MyObject(dict: item as NSDictionary)
callbackArray.append(arrayItem)
}
callback(callbackArray)
} else {
// handle an error
}
}
dataTask.resume()
}
Then you could do something like:
getSomething() { (response) in
if let responseArray = response as? Array<MyObject> {
self.somethings = responseArray
}
}
How can I return value from completion block to use it in other viewController?
queryCompletionBlock
is executed asynchronously so by the time print(self.kcalUnitValid)
is called queryCompletionBlock
wouldn't have finished its execution yet, in other words, the order in how execution happens is like below sequentially:
- 1.-
queryOperation.queryCompletionBlock(..)
is called - 2.-
print(self.kcalUnitValid)
is called// prints empty
- 3.- after some seconds the result of
queryOperation.queryCompletionBlock(..)
is returned
Code
What you could do it probably is this:
func KcalCloudKitData() {
// .. code omitted
queryOperation.queryCompletionBlock = {cursor, error in
if error != nil {
// .. code omitted
} else {
for value in self.allRecords {
self.kcalUnitValid.append(value.object(forKey: "KcalValidUnit") as! [String])
}
// Segue to another ViewController
// And also sending kcalUnitValid
self.performSegue(withIdentifier: "AppLoaded", sender: self.kcalUnitValid)
}
}
// .. code omitted
}
// Actually in this method is when you decide
// what data you are going to send to the AnotherViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AppLoaded" {
let anotherViewController = segue.destination as! AnotherViewController
anotherViewController.kcalUnitValid = sender as! Array<[String]>
}
}
Resources:
Watch this video explaning async programming in Swift
swift 3 calling function with completion closure in return
You can't return from a closure. Also, note that your function is making a webservice call. When that part is encountered, the control doesn't go into the block immediately and the entire function execution will be over before the block is executed. Instead of returning a value you can add another completion block to your login function. Add another argument to your login
function.
public func login(userName: String, password: String, completion: @escaping(Any)->Void)
Inside the login function, remove the return statement and do something like this
makeWebServiceCall(urlAddress: URL, requestMethod: .post, params: loginrequest, completion: { (JSON : Any) in
completion(JSON)
})
And when you call your login function all you have to do is,
login(userName: "", password:""){(response) in
print(response)
}
You'll have the data that you wanted to pass here
Related Topics
Using Custom Cifilter on Calayer Shows No Change to Calayer
Swift Find Superview of Given Class with Generics
Different Colors for Bars in Barchart Depend on Value
Uicollectionview Autosize and Dynamic Number of Rows
Unknown Error When Adding an CSSearchableitem to Core Spotlight (Macos)
Core Data: Rename Attribute Without Having Issues with Users and Their Current Data
How to Get the List of Open Windows on MACos in Swift
Implementing "User Stopped Speaking" Notification for 'Sfspeechrecognizer'
Bit Field Larger Than 64 Shifts in Swift
Swift: Nsstatusitem Menu Behaviour in 10.10 (E.G. Show Only on Right Mouse Click)
How to Give PDF Data a Filename for User to Save in Swift
Accessibility (Voice Over) with Sprite Kit
Correct Way to Call "Realloc" in Swift with a Float Array
How to Return a Button from a Function in Swiftui