How to return value from Alamofire How to return value from Alamofire ios ios

How to return value from Alamofire


As mattt points out, Alamofire is returning data asynchronously via a “completion handler” pattern, so you must do the same. You cannot just return the value immediately, but you instead want to change your method to not return anything, but instead use a completion handler closure pattern.

Nowadays, that might look like:

func getOrders(completionHandler: @escaping (Result<[String: Any]>) -> Void) {    performRequest("orders", completion: completionHandler)}func performRequest(_ section: String, completion: @escaping (Result<[String: Any]>) -> Void) {    let url = baseURL.appendingPathComponent(section)    let params = ["consumer_key": "key", "consumer_secret": "secret"]    Alamofire.request(url, parameters: params)        .authenticate(user: consumerKey, password: consumerSecret)        .responseJSON { response in            switch response.result {            case .success(let value as [String: Any]):                completion(.success(value))            case .failure(let error):                completion(.failure(error))            default:                fatalError("received non-dictionary JSON response")            }    }}

Then, when you want to call it, you use this completion closure parameter (in trailing closure, if you want):

api.getOrders { result in    switch result {    case .failure(let error):        print(error)    case .success(let value):        // use `value` here    }}// but don't try to use the `error` or `value`, as the above closure// has not yet been called//


From the Alamofire README (emphasis added):

Networking in Alamofire is done asynchronously. Asynchronous programming may be a source of frustration to programmers unfamiliar with the concept, but there are very good reasons for doing it this way.

Rather than blocking execution to wait for a response from the server, a callback is specified to handle the response once it's received. The result of a request is only available inside the scope of a response handler. Any execution contingent on the response or data received from the server must be done within a handler.


Following is the complete flow for performing the 'Login Action' using Alamofire and Swift.

Alamofire v3.3Swift 2.2Xcode 7.3

I have used GCD and MBProgressHUD for my own convenience. Refactor and use as you like :)

func loginBtnTapped(sender: AnyObject) {    MBProgressHUD.showHUDAddedTo(self.view, animated: true)    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {        let loginInfo : Dictionary<String,AnyObject> = ["email":"abc@g.com","password":"abc123"]        self.loginUser(loginInfo) { responseObject, error in            print("\(responseObject) \n  \(error) ")            // Parsing JSON Below            let status = Int(responseObject?.objectForKey("status") as! String)            if status == 1 {                // Login Successfull...Move To New VC            }            else {                print(responseObject?.objectForKey("message"))! as! String)            }            return        }        dispatch_async(dispatch_get_main_queue()) {            MBProgressHUD.hideHUDForView(self.view, animated: true)        }    }}func loginUser(parameters:NSDictionary, completionHandler: (NSDictionary?, NSError?) -> ()) {    self.postRequest("http://qa.company.com/project/index.php/user/login",                     paramDict: parameters as? Dictionary<String, AnyObject>,                     completionHandler: completionHandler)}func postRequest(urlString: String, paramDict:Dictionary<String, AnyObject>? = nil,                 completionHandler: (NSDictionary?, NSError?) -> ()) {    Alamofire.request(.POST, urlString, parameters: paramDict)        .responseJSON { response in            switch response.result {            case .Success(let JSON):                completionHandler(JSON as? NSDictionary, nil)            case .Failure(let error):                completionHandler(nil, error)            }    }}