How I can return value from async block in swift
Like @rmaddy said, you have no other way than to use completion handlers.
func getAppConfigFromDB(_ key: String, completion: @escaping ((String) -> Void)) {
let value = String()
backgroundthread.async {
let inst = AppConfigDB.init(_APP_CONFIG_DB_PATH)
value = inst.getConfigurationInfo(key) // I want to return from here.
completion(value)
}
}
You call the method like this.
getAppConfigFromDB("") { (value) in
// Use value to do something
}
How can i return value from async block?
You can pass completion closure and after success or failure request execute it.
func xmlRequest(_ id:Int, completion: @escaping ((String) -> Void)){
var array1:Array<Any> = Array<Any>();
array1.append("body" as Any);
array1.append("date" as Any);
array1.append("author_id" as Any);
let con:NSDictionary = NSDictionary();
var field2:Array<Any> = Array<Any>();
field2.append([["id", "=", [id]]]);
let url = Login.BASEURL+XMLRPC_SERVICE_OBJECT;
let param3 = [Login.DATABASE, Login.LOGIN_ID, Login.PASSWORD, "mail.tracking.value","search_read",field2,con] as [Any];
AlamofireXMLRPC.request(url, methodName: "execute_kw", parameters: param3).responseXMLRPC { (response: DataResponse<XMLRPCNode>) in
var valueToReturn:String = "default"
switch response.result {
case .success(let value):
valueToReturn = "success"
case .failure(let error):
valueToReturn = "error"
}
completion(valueToReturn)
}
}
More about closures you can read at Apple documentation =)
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html
swift calling async function without a return value
What you're describing is a Task. For example:
Task { await `do`() }
stuff()
This will run do()
concurrently with stuff()
. If you need to keep track of when do()
completes, you can await the task's value:
let task = Task { await `do`() }
stuff()
await task.value // Doesn't actually return anything, but will block
This kind of Task runs in the context of the current Actor, which is usually what you want. If you want something independent of the current Actor, you can use Task.detached()
instead.
If you've previously used DispatchQueues, in many of the places you would have written queue.async { ... }
, you can now write Task { ... }
. The new system is much more powerful, but it maps fairly nicely to the old system if you want it to.
Can Swift return value from an async Void-returning block?
You should employ asynchronous (ie, escaping) completion handler yourself:
class func checkIfUserExists(uid: String, completion: @escaping (Bool) -> Void) {
userRef.childByAppendingPath(uid).observeSingleEventOfType(.Value) { snapShot in
if snapShot.value is NSNull {
completion(false)
} else {
completion(true)
}
}
}
You can then call this like so:
MyClass.checkIfUserExists(uid) { success in
// use success here
}
// but not here
In your revised question, you demonstrate the use of dispatch groups to make this asynchronous method behave synchronously. (Semaphores are also often used to the same ends.)
Two issues:
This will deadlock if they dispatch their completion handler back to the main queue (and in many cases, libraries will do this to simplify life for us), because you're coincidentally blocking the very same thread they're trying to use. I don't know if that's what they've done here, but is likely.
If you want to confirm this, temporarily remove dispatch group and then examine
NSThread.isMainThread
and see if it's running in main thread or not.You never should block the main thread, anyway. They provided an asynchronous interface for good reason, so you should use asynchronous patterns when calling it. Don't fight the asynchronous patterns, but rather embrace them.
Swift write an async/await method with return value
Thanks, vadian comment. I used a closure as an input parameter of the method.
// MARK: - PassCode Methods
func checkPassCode(completionHandler:@escaping (_ flag:Bool) -> ()) {
let storePin = getStorePin()
let userPin = self.pin.joined(separator: "")
AsymmetricCryptoManager.sharedInstance.decryptMessageWithPrivateKey(storePin as Data) { (success, result, error) -> Void in
if success {
let pin = result!
print("userPin is: \(userPin)")
print("storePin is: \(pin)")
completionHandler(userPin == pin)
} else {
print("Error decoding base64 string: \(String(describing: error))")
completionHandler(false)
}
}
}
func getStorePin() -> NSData {
if let pin = self.keychain.get("pin") {
return NSData(base64Encoded: pin, options: []) ?? NSData()
}
return NSData()
}
and then call this method:
checkPassCode { success in
if success {
print("sucess")
} else {
print("not sucess!")
}
}
return value from completion handler is not updated in DispatchQueue.main.async block
The call of completion
is at the wrong place. Move it into the completion closure of the data task after the print line
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
completion(self.avgMonthlyAcKw)
and delete it after resume
dataTask.resume()
completion(self.avgMonthlyAcKw)
}
iOS - Swift - Function that returns asynchronously retrieved value
Yes, it is possible to do this. Its called a closure
, or more commonly a callback
. A callback
is essentially a function that you can use as an argument in another functions. The syntax of the argument is
functionName: (arg0, arg1, arg2, ...) -> ReturnType
ReturnType
is usually Void
. In your case, you could use
result: (image: UIImage?) -> Void
The syntax of calling a function with one callback in it is
function(arg0, arg1, arg2, ...){(callbackArguments) -> CallbackReturnType in
//code
}
And the syntax of calling a function with several callbacks is (indented to make it easier to read)
function(
arg0,
arg1,
arg2,
{(cb1Args) -> CB1Return in /*code*/},
{(cb2Args) -> CB2Return in /*code*/},
{(cb3Args) -> CB3Return in /*code*/}
)
If your callback function escapes the main function (the callback is called after the main function returns), you must add @escaping in front of the callback's argument type
You're going to want to use a single callback that will be called after the function returns and that contains UIImage?
as the result.
So, your code could look something like this
func imageFromFile(file: PFFile, result: @escaping (image: UIImage?) -> Void){
var image: UIImage?
file.getDataInBackgroundWithBlock() { (data: NSData?, error: NSError?) -> Void in
//this should be 'error == nil' instead of 'error != nil'. We want
//to make sure that there is no error (error == nil) before creating
//the image
if error == nil {
image = UIImage(data: data!)
result(image: image)
}
else{
//callback nil so the app does not pause infinitely if
//the error != nil
result(image: nil)
}
}
}
And to call it, you could simply use
imageFromFile(myPFFile){(image: UIImage?) -> Void in
//use the image that was just retrieved
}
how to use DispatchGroup to return a async value from a function
You need
class ViewController: UIViewController {
var coffeeMachineName = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
dev.adData.getMachineName { (mName) in
print("machine name from wbmanager: \(mName)")
self.coffeeMachineName = mName
DispatchQueue.main.async {
pickerView.reloadAllComponents()
}
}
}
private func _pv(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String {
let dev = self.pickerDevices[row]
let id = dev.internalUUID
guard let name = dev.name
else {
return "\(id)"
}
return "\(name) \(self.coffeeMachineName)"
}
}
Related Topics
How to Cycle Through the Entire Alphabet with Swift While Assigning Values
How to Get the Index of the Element in the List in Swiftui When the List Is Populated with the Array
How to Create a View-Based Nstableview Purely in Code
Xcode 9 and Xcode 10 Giving Different Results, Even with Same Swift Version
Obervableobject Being Init Multiple Time, and Not Refreshing My View
Swift Dictionary Default Value
Uitableviewautomaticdimension Not Working for Resizing Cell Height
How to Obtain the Selected Text from the Frontmost Application in MACos
Using Combine's Future to Replicate Async Await in Swift
Downloading and Caching Images from Url Asynchronously
How to Generate Large, Ranged Random Numbers in Swift
Checking for Nil Value in Swift Dictionary Extension
Swift Struct Type Recursive Value
How to Get the File Creation Date Using Url Resourcevalues Method in Swift 3
Whats the Swift Animate Withduration Syntax
Should Conditional Compilation Be Used to Cope With Difference in Cgfloat on Different Architectures