【发布时间】:2015-06-13 19:48:55
【问题描述】:
我刚开始使用 Swift 进行开发,所以我对闭包完全陌生。我也是如何处理异步 API 请求的新手。
我读过很多类似的问题,例如How to get data to return from NSURLSessionDataTask in Swift 和How to use completionHandler Closure with return in Swift?。这些对我有帮助,但我的问题有点不同。
在我的函数中,我想首先发出 API 请求以获取 JSON 有效负载。有了这个 JSON 有效负载中的一些数据,我想发出多个其他 API 请求。在这种情况下,我将为每个 API 请求接收一个 JSON 有效负载,其中我想将一些数据存储在我自己的 JSON 数据结构中。
问题是,对于我发出的每个多个 API 请求,我只能在 CompletionHandler 中返回我自己的部分 JSON 数据 - 据我所知,这是使用闭包发出 API 请求时返回数据的唯一方法.
因此,在调用我的函数时,我只想接收一个,而不是获取多个完成处理程序。
问题是我不知道如何在一个函数中完成处理多个闭包,在这种情况下是两个闭包。
我在下面发布了我的代码 - 我知道它很长而且可能不是那么干净。 但是,关键是当我将优惠更新到我的 storeDict 时,这将是空的,因为优惠 dict 数组正在从第二个闭包内部获取其信息。这显示在函数的底部。
func getOffersFromWishList(offerWishList: [String], latitude: Double, longitude: Double, radius: Int, completionHandler: ([NSDictionary] -> Void)) {
var master: [NSDictionary] = []
var nearby_params: NSDictionary = ["r_lat": latitude, "r_lng": longitude, "r_radius": radius]
//println(nearby_params)
var store_id_list: [String] = []
// Get all store_ids for store which are nearby (Radius determines how nearby)
singleton_eta.api("/v2/stores", type: ETARequestTypeGET, parameters: nearby_params, useCache: true, completion: { (response, error, fromCache) -> Void in
if error == nil {
let json = JSON(response)
storeArray = json.arrayValue
//println(storeArray)
for store in storeArray {
var storeDict = [String: AnyObject]()
var metaData = [String: String]()
var offers: [NSDictionary] = []
let name = store["branding"]["name"].stringValue
let store_id = store["id"].stringValue
let street = store["street"].stringValue
let city = store["city"].stringValue
let zip_code = store["zip_code"].stringValue
let dealer_id = store["dealer_id"].stringValue
let logo = store["branding"]["logo"].stringValue
metaData = ["name": name, "store_id": store_id, "street": street, "city": city, "zip_code": zip_code, "dealer_id": dealer_id, "logo": logo]
store_id_list.append(store_id)
//println("Butiks ID: \(store_id)")
var offset = 0
let limit = 100
// Loop through the offers for the specific store id - only possible to request 100 offers each time
// A while loop would be more suitable, but I dont know when to stop, as the length of the offerArray can not be counted as it is cant be accessed outside of the closure.
for x in 1...2 {
var store_params: NSDictionary = ["store_ids:": store_id, "limit": limit, "offset": offset]
println(store_params)
// Get offers for a specific store_id
singleton_eta.api("/v2/offers", type: ETARequestTypeGET, parameters: store_params, useCache: true, completion: { (response, error, fromCache) -> Void in
if error == nil {
offerArray = JSON(response).arrayValue
//println( "TypeName0 = \(_stdlib_getTypeName(offerArray))")
//Loop through the recieved offers
for of in offerArray {
let name = of["branding"]["name"].stringValue
let dealer_id = of["dealer_id"].stringValue
let heading = of["heading"].stringValue
let description = of["description"].stringValue
let price = of["pricing"]["price"].stringValue
let image = of["images"]["view"].stringValue
//println(heading)
// Loop through our offerWishList
for owl in offerWishList {
let headingContainsWish = (heading.lowercaseString as NSString).containsString(owl.lowercaseString)
// Check if offer match with our wish list
if(headingContainsWish) {
// Save neccesary meta data about each offer to a tuple array
var offer = Dictionary<String, String>()
offer = ["name": name, "dealer_id": dealer_id, "heading": heading, "description": description, "price": price, "image": image, "offerWishItem": owl]
offers.append(offer)
}
}
}
}
})
//println(storeDict)
offset = offset + limit + 1
}
storeDict.updateValue(metaData, forKey: "meta_data")
storeDict.updateValue(offers, forKey: "offers") // offers is empty due to its appending inside the closure
master.append(storeDict)
}
completionHandler(master)
}
else {
println(error)
}
})
}
调用上述函数
getOffersFromWishList(offerWishList, latitude, longitude, radius) { (master) -> Void in
println(master)
}
这是master在调用函数时会打印的内容,其中offers为空。
{
"meta_data" = {
city = "Kongens Lyngby";
"dealer_id" = d8adog;
logo = "https://d3ikkoqs9ddhdl.cloudfront.net/img/logo/default/d8adog_3qvn3g8xp.png";
name = "d\U00f8gnNetto";
"store_id" = d2283Zm;
street = "Kollegiebakken 7";
"zip_code" = 2800;
};
offers = (
);
}
{
...
}
所以我的问题是,在函数内将数据从第二个闭包返回到第一个闭包的正确方法是什么?还是我以完全错误的方式这样做? 问题是,我需要所有这些数据用于 tableview,因此需要一次所有数据。
【问题讨论】:
标签: api swift asynchronous closures