如何一个接一个地下载和处理2组数据?

我正在做一个web服务调用来获取数据列表。 在收到所有这些数据之后,我想打个电话给列表中的每个项目。 这是我有这么多的代码:

let zipcde:String = self.zipCode let username:String = "tr1gger" //webservice call var listZip = [String]() let wsUrl: NSURL = NSURL(string: "http://api.url.org/findNearbyTheseCodesJSON?postalcode=" + zipcde + "&maxRows=100&country=US&radius=25&username=" + username)! let task = NSURLSession.sharedSession().dataTaskWithURL(wsUrl, completionHandler: { (data, response, error) -> Void in //will happen when task is complete if let urlContent = data { let jsonObject = JSON(data: urlContent) if let jsonDict:JSON = jsonObject["postalCodes"]{ let postalCode = "postalCode" for var i:Int = 0; i < jsonDict.count; i++ { print("Property: \"\(jsonDict[i][postalCode])\"") listZip.append(String(jsonDict[i][postalCode])) } self.showLoadingMessage() self.listOfZips = listZip self.getStores() } } }) task.resume() 

self.getStores是一个函数,它开始一个for循环,并为第一个列表中的每个项目调用webservice:

 func getStores(){ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), { for areaCode in self.listOfZips{ let url = NSURL(string: "http://myUrl.thisPlace.net/getStores.php?zipcode=" + areaCode + "&ammoType=" + self.aType)! let task2 = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data2, response2, error2) -> Void in if let jsonObject2: NSArray = (try? NSJSONSerialization.JSONObjectWithData(data2!, options: NSJSONReadingOptions.MutableContainers)) as? NSArray{ var storeName = [String]() var storeAddress = [String]() var storeId = [String]() var ammoStId = [String]() var ammoStock = [String]() var ammoPrice = [String]() for obj in jsonObject2{ if let name: String = obj["storeName"] as? String{ storeName.append(name) storeAddress.append((obj["storeAddress"] as? String)!) storeId.append((obj["storeId"]as? String)!) } else if let id: String = obj["storeId"] as? String{ ammoStId.append(id) ammoStock.append((obj["ammoStock"] as? String)!) if let priceTemp: String = obj["ammoPrice"] as? String{ ammoPrice.append(priceTemp) } } } var storeList = [StoreItem]() for var index:Int = 0; index < storeId.count; ++index{ let sId = storeId[index] for var i:Int = 0; i < ammoStId.count; ++i{ let aId = ammoStId[i] if sId == aId{ //creating object let storeItem:StoreItem = StoreItem() storeItem.setAddress(storeAddress[index]) storeItem.setName(storeName[index]) storeItem.setId(Int(storeId[index])!) storeItem.setAmmoStock(Int(ammoStock[i])!) storeItem.setAmmoPrice(ammoPrice[i]) storeList.append(storeItem) } } } self.storeListFinal.appendContentsOf(storeList) } self.myAlert.dismissViewControllerAnimated(true, completion: nil) self.tableView.reloadData() }) task2.resume() } }) 

正如你所看到的,我在这个调用结束时正在填充一个表格。 此代码需要大约18-20秒才能完成。 在我的Android版本,它需要2秒。 我怎样才能优化这个?

谢谢你的帮助。

在后台线程中调用UI更新(重新加载表)可能会导致延迟。 所以,你应该将UI更新代码移动到主线程:

 let task2 = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data2, response2, error2) -> Void in .... dispatch_async(dispatch_get_main_queue(), { self.myAlert.dismissViewControllerAnimated(true, completion: nil) self.tableView.reloadData() }) }) 

上面的这种方式可以临时解决你的问题,但是,它会重新载入你多次的表,因为你在循环中创build了许多任务。 你应该想办法改善这一点。

我正在做一个web服务调用来获取数据列表。 在收到所有这些数据之后,我想打个电话给列表中的每个项目。

这种情况正是 WWDC 2015高级NSOperationsvideo的主题。 通过使用NSOperation封装每个networking的“任务”,您可以创build所需的依赖关系(Web服务调用必须在其他任何事情发生之前成功完成),并排队其他“任务”(每个项目的Web调用)所有这些都是独立完成的。 如果以这种方式使用NSOperations,将会发现expression这种有序依赖的逻辑更容易expression。 观看video,你会明白我的意思。

你使用了共享的NSURLSession ,看起来该会话排队你所要求的。 辅助查询不会在同一时间执行,我认为这是性能下降的原因。

您可以通过以下代码更改每个主机的最大并发连接数:

 NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration]; config.HTTPMaximumConnectionsPerHost = 20; 

在创build任何共享的NSURLSession之前,可能必须调用上面的代码。 为了确定,我build议你应该创build一个使用明确定义的configuration的自定义NSURLSession。

PS。 国际海事组织,改变服务脚本,所以服务器可以提供结果只有1个电话是最好的解决scheme,如果你可以。

使用dispatch_sync和后台线程。 你可以在我的文章中find解决scheme: Swift Serial Dispatch Block只有在委托之后才能完成