如何从Alamofire返回价值
我正在通过我使用swift创build的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 } }
我在我的UITableViewController
调用这个API来使用SwiftyJSON库填充表。 不过,我从API的returnData
总是空的。 Alomofire调用没有问题,因为我可以成功检索值。 我的问题是我应该如何将这些data
传递给我的表视图控制器?
var api = API() api.getOrders() println(api.returnData) // returnData is empty
正如mattt指出的,Alamofire通过completionHandler
模式asynchronous返回数据,所以你必须这样做。 你不能直接return
值,而是你想使用Void
返回types,而是使用完成处理程序闭包模式。
在Swift 3和Alamofire 4中,这可能看起来像:
func getOrders(completionHandler: @escaping (NSDictionary?, Error?) -> ()) { makeCall("orders", completionHandler: completionHandler) } func makeCall(_ section: String, completionHandler: @escaping (NSDictionary?, Error?) -> ()) { let params = ["consumer_key":"key", "consumer_secret":"secret"] Alamofire.request("\(apiUrl)/\(apiEndPoint + section)", parameters: params) .authenticate(user: consumerKey, password: consumerSecret) .responseJSON { response in switch response.result { case .success(let value): completionHandler(value as? NSDictionary, nil) case .failure(let error): completionHandler(nil, error) } } }
然后,当你想调用它的时候,你可以使用这个completionHandler
参数(如果你愿意,可以在尾部closures中使用):
let api = API() api.getOrders() { responseObject, error in // use responseObject and error here print("responseObject = \(responseObject); error = \(error)") return } // but don't try to use them here
来自Alamofire自述文件(重点补充):
Alamofirenetworking是asynchronous完成的。 asynchronous编程对于不熟悉这个概念的程序员来说可能是一个令人沮丧的来源,但是这样做有很好的理由。
不是阻止执行来等待来自服务器的响应,而是指定一个callback来处理收到的响应。 请求的结果只在响应处理程序的范围内可用。 从服务器收到的响应或数据的任何执行都必须在处理程序中完成 。
以下是使用Alamofire和Swift执行“login操作”的完整stream程。
Alamofire v3.3 Swift 2.2 Xcode 7.3
为了方便,我使用了GCD和MBProgressHUD 。 重构和使用,只要你喜欢:)
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) } } }
使用Swifty JSONparsing一个json,这里是我如何做的。
对于@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!) }