How to return value from Alamofire

前端 未结 5 1962
忘掉有多难
忘掉有多难 2020-11-22 02:41

I am making url calls thru an API that I created using swift as follows:

class API {

  let apiEndPoint = \"endpoint\"
  let apiUrl:String!
  let consumerKey         


        
相关标签:
5条回答
  • 2020-11-22 03:09

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

    Alamofire v3.3 Swift 2.2 Xcode 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)
                }
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 03:10

    To parse a json using Swifty JSON, here is how i am doing it.

    For @Jenita _Alice4Real

    func uploadScans(parameters: [String: AnyObject], completionHandler: (AnyObject?, NSError?) -> ()) {
        makePostCall(CommonFunctions().getSaveSKUDataUrl(), parameters: parameters,completionHandler: completionHandler)
    }
    
    func makePostCall(url: String, parameters: [String: AnyObject], completionHandler: (AnyObject?, NSError?) -> ()) {
        Alamofire.request(.POST, url, parameters: parameters)
            .responseJSON { response in
                switch response.result {
                    case .Success(let value):
                        completionHandler(value, nil)
                    case .Failure(let error):
                        completionHandler(nil, error)
                }
        }
    }
    
    uploadScans(params) { responseObject, error in
        let json = JSON(responseObject!)
    }
    
    0 讨论(0)
  • 2020-11-22 03:18

    Details

    xCode 9.1, Swift 4

    Features:

    • Easy readable code
    • Ready templates (it's easy to add more requests)
    • Embedded solution with asynchronous data processing
    • Full examples

    Sample 1

    Return data using closure

    Data1.searchRequest(term: "jack johnson") { json, error  in
         print(error ?? "nil")
         print(json ?? "nil")
         print("Update views")
    }
    

    Full sample 1

    Data class

    import Alamofire
    
    class Data1 {
    
        static fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility)
        static fileprivate let mainQueue = DispatchQueue.main
    
        fileprivate class func make(request: DataRequest, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) {
            request.responseJSON(queue: Data1.queue) { response in
    
                // print(response.request ?? "nil")  // original URL request
                // print(response.response ?? "nil") // HTTP URL response
                // print(response.data ?? "nil")     // server data
                //print(response.result ?? "nil")   // result of response serialization
    
                switch response.result {
                case .failure(let error):
                    Data1.mainQueue.async {
                        closure(nil, error)
                    }
    
                case .success(let data):
                    Data1.mainQueue.async {
                        closure((data as? [String: Any]) ?? [:], nil)
                    }
                }
            }
        }
    
        class func searchRequest(term: String, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) {
            let request = Alamofire.request("https://itunes.apple.com/search?term=\(term.replacingOccurrences(of: " ", with: "+"))")
            Data1.make(request: request) { json, error in
                closure(json, error)
            }
        }
    }
    

    UIViewController

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            Data1.searchRequest(term: "jack johnson") { json, error  in
                print(error ?? "nil")
                print(json ?? "nil")
                print("Update views")
            }
        }
    }
    

    Sample 2

    Return data using delegate

    // ....
    var data = Data2()
    data.delegate = self
    data.searchRequest(term: "jack johnson")
    // ....
    
    extension ViewController: Data2Delegate {
        func searchRequest(response json: [String : Any]?, error: Error?) {
            print(error ?? "nil")
            print(json ?? "nil")
            print("Update views")
        }
    }
    

    Full sample 2

    Data class

    import Alamofire
    
    protocol Data2Delegate: class {
        func searchRequest(response json: [String: Any]?, error: Error?)
    }
    
    class Data2 {
    
        fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility)
        fileprivate let mainQueue = DispatchQueue.main
    
        weak var delegate: Data2Delegate?
    
        fileprivate func make(request: DataRequest, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) {
            request.responseJSON(queue: queue) { response in
    
                // print(response.request ?? "nil")  // original URL request
                // print(response.response ?? "nil") // HTTP URL response
                // print(response.data ?? "nil")     // server data
                //print(response.result ?? "nil")   // result of response serialization
    
                switch response.result {
                case .failure(let error):
                    self.mainQueue.async {
                        closure(nil, error)
                    }
    
                case .success(let data):
                    self.mainQueue.async {
                        closure((data as? [String: Any]) ?? [:], nil)
                    }
                }
            }
        }
    
        func searchRequest(term: String) {
            let request = Alamofire.request("https://itunes.apple.com/search?term=\(term.replacingOccurrences(of: " ", with: "+"))")
            make(request: request) { json, error in
                self.delegate?.searchRequest(response: json, error: error)
            }
        }
    }
    

    UIViewController

    import UIKit
    
    class ViewController: UIViewController {
        private var data = Data2()
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            data.delegate = self
            data.searchRequest(term: "jack johnson")
        }
    }
    
    extension ViewController: Data2Delegate {
        func searchRequest(response json: [String : Any]?, error: Error?) {
            print(error ?? "nil")
            print(json ?? "nil")
            print("Update views")
        }
    }
    

    Sample 3

    Return data using PromiseKit

    _ = data.searchRequest(term: "jack johnson").then { response in
          print(response.error ?? "nil")
          print(response.json ?? "nil")
          print("Update views")
          return .void
    }
    

    Full sample 3

    Data class import Alamofire import PromiseKit

    class Data3 {
    
        fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility)
        fileprivate let mainQueue = DispatchQueue.main
    
        fileprivate func make(request: DataRequest) -> Promise<(json:[String: Any]?, error: Error?)> {
             return Promise { fulfill, reject in
                request.responseJSON(queue: queue) { response in
    
                    // print(response.request ?? "nil")  // original URL request
                    // print(response.response ?? "nil") // HTTP URL response
                    // print(response.data ?? "nil")     // server data
                    //print(response.result ?? "nil")   // result of response serialization
    
                    switch response.result {
                        case .failure(let error):
                            self.mainQueue.async {
                                fulfill((nil, error))
                            }
    
                        case .success(let data):
                            self.mainQueue.async {
                                fulfill(((data as? [String: Any]) ?? [:], nil))
                            }
                    }
                }
            }
        }
    
        func searchRequest(term: String) -> Promise<(json:[String: Any]?, error: Error?)> {
            let request = Alamofire.request("https://itunes.apple.com/search?term=\(term.replacingOccurrences(of: " ", with: "+"))")
            return make(request: request)
        }
    }
    
    extension AnyPromise {
    
        class var void: AnyPromise {
            return AnyPromise(Promise<Void>())
        }
    }
    

    UIViewController

    import UIKit
    import PromiseKit
    
    class ViewController: UIViewController {
        private var data = Data3()
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            _ = data.searchRequest(term: "jack johnson").then { response in
                print(response.error ?? "nil")
                print(response.json ?? "nil")
                print("Update views")
                return .void
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 03:20

    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
    //
    
    0 讨论(0)
  • 2020-11-22 03:20

    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.

    0 讨论(0)
提交回复
热议问题