Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
126 views
in Technique[技术] by (71.8m points)

ios - How to return value from Alamofire

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:String!
  let consumerSecret:String!

  var returnData = [:]

  init(){
    self.apiUrl = "https://myurl.com/"
    self.consumerKey = "my consumer key"
    self.consumerSecret = "my consumer secret"
  }

  func getOrders() -> NSDictionary{
    return makeCall("orders")
  }

  func makeCall(section:String) -> NSDictionary{

    let params = ["consumer_key":"key", "consumer_secret":"secret"]

    Alamofire.request(.GET, "(self.apiUrl)/(self.apiEndPoint + section)", parameters: params)
        .authenticate(user: self.consumerKey, password: self.consumerSecret)
        .responseJSON { (request, response, data, error) -> Void in
            println("error (request)")
            self.returnData = data! as NSDictionary
    }
    return self.returnData
  }

}

I call this API in my UITableViewController to populate the table with SwiftyJSON library. However my returnData from the API is always empty. There is no problem with Alomofire calls as I can successfully retrieve value. My problem is how I am supposed to carry this data over to my table view controller?

var api = API()
api.getOrders()
println(api.returnData) // returnData is empty
Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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
//

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...