如何从Alamofire返回价值

u54*_*54r 57 ios swift alamofire

我通过使用swift创建的API进行url调用,如下所示:

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
  }

}
Run Code Online (Sandbox Code Playgroud)

我在我的API中调用这个API UITableViewController来使用SwiftyJSON库填充表.但是我returnData的API总是空的.Alomofire调用没有问题,因为我可以成功检索值.我的问题是我应该怎么把它data带到我的表视图控制器?

var api = API()
api.getOrders()
println(api.returnData) // returnData is empty
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 97

正如mattt指出的那样,Alamofire通过return模式异步返回数据,所以你必须这样做.您不能completion立即使用该值,而是希望使用return返回类型,而是使用完成处理程序闭包模式.

在Swift 3和Alamofire 4中,可能看起来像:

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")
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当你想调用它时,你使用这个completion参数(在尾随闭包中,如果你想):

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
//
Run Code Online (Sandbox Code Playgroud)

  • 正确,这不会"返回"任何东西.它不能,因为它以异步方式运行.在`viewDidLoad`中调用`getOrders`,例如在`getOrders`完成块(我打印`responseObject`)中,你将(a)用异步调用的结果更新你的属性; (b)从完成闭包中调用`[self.tableView reloadData]`.因此,您的`UITableViewDataSource`方法将在您第一次加载时被调用两次(此时没有数据可用); 再次调用`reloadData`之后. (3认同)
  • @Granola - 啊,我误解了.Xcode为您提供了分段错误,而不是您的应用.看起来更新的Alamofire语法会导致编译器出现问题.您可以使用`switch`语句独立检查`.Success`和`.Failure`,这可以解决这个问题.它不是那么紧凑,但更清楚的是处理Alamofire`Result``enum`. (2认同)
  • 完善!谢谢你.我的代码现在更清晰,更正确.对于所有异步调用,这应该是这样的.如果要将响应解析为json,只需要进行更改:而不是```completionHandler(值为?NSDictionary,nil)```只需```completionHandler(value,nil)```并替换``` ```getOrders```中的NSDictionary```和```AnyObject```的```makeCall```.value是responseObject.您现在可以在处理程序中解析此值,如下所示:```let json = JSON(responseObject!)``` (2认同)

mat*_*ttt 13

来自Alamofire README(重点补充):

Alamofire中的网络是异步完成的.对于不熟悉这个概念的程序员来说,异步编程可能会让人感到沮丧,但是有很好的理由这样做.

而不是阻止执行以等待来自服务器的响应,而是指定回调一旦收到响应就处理响应.请求的结果仅在响应处理程序的范围内可用.根据响应或从服务器接收的数据执行的任何执行都必须在处理程序内完成.