How to download and process 2 sets of data, one after the other?

自作多情 提交于 2020-01-17 04:49:18

问题


I am making a webservice call to get a list of data. After I have all of that data I would like to make a web call for every item on that list. Here is the code I have this far:

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()

the self.getStores is a function that begins a for loop and calls a webservice for every item on the first list:

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()
  }
})

As you can see I am populating a table at the end of this call. This code takes about 18-20 seconds to finish. On my android version it takes like 2 seconds. How can I optimize this?

Thanks for any help.


回答1:


Invoke UI update (reload table) in background thread can cause delay. So, you should move the UI update code to main thread:

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()
      })

    })

This way above can temporary solve your problem, but, it will reload you table many times because you create many tasks in loop. You should think another way to improve this.




回答2:


I am making a webservice call to get a list of data. After I have all of that data I would like to make a web call for every item on that list.

This sort of situation is exactly the subject of the WWDC 2015 video on Advanced NSOperations. By using an NSOperation to encapsulate each your network "tasks", you can create the dependencies you need (the web service call must complete successfully before anything else can happen) and queue up the other "tasks" (the web call for each item) so that they are all performed independently and in good order. You'll find that the logic of expressing this sort of ordered dependency is much easier to express if you use NSOperations in this way. Watch the video, you'll see what I mean.




回答3:


You used shared NSURLSession and it seems to that session queued what you requested. The secondary queries are not executed in same time, I think this is the reason for slow performance.

You can change max concurrent connection count for each host by below code:

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

Above codes may have to be called before any shared NSURLSession is created. To make it sure, I suggest that you should create a custom NSURLSession that uses explicitly defined configuration.

ps. IMO, changing serve scripts so the sever can provide results with just 1 call is Best Solution if You can.




回答4:


use, dispatch_sync with background thread. You can find solution, in my post, there: Swift Serial Dispatch Block only finish after delegate



来源:https://stackoverflow.com/questions/33178204/how-to-download-and-process-2-sets-of-data-one-after-the-other

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!