2017-07-12 181 views
0

我正在嘗試從for循環中的多個GET請求中下載數據,然後將其添加到表視圖中。 我成功地獲取數據,但遇到的問題是主線程在所有數據從請求中下載之前一直運行,因此它不會加載到表視圖中。 我想使用信號量一次嘗試運行一個線程,但它似乎並沒有工作。 下面是代碼:(Swift)在for循環中使用帶NSURLSession的信號量

for item in array{ 
    let http = item["http"] as! String 
    let URL = NSURL(string: http) 
    let Request = NSMutableURLRequest(url: URL! as URL) 
    Request.setValue(self.headerVal, forHTTPHeaderField: "Authorization") 
    Request.httpMethod = "GET" 
    let UrlSession = URLSession.shared 
    let Info = UrlSession.dataTask(with: Request as URLRequest) { (data, response, error) -> Void in 
     if error != nil{ 
      print(error!) 
      return; 
     } 
     else{ 
      do{ 
       let ResponseData = try JSONSerialization.jsonObject(with: data!) as! [String:Any] 
       guard let results = ResponseData["data"] as? [Any] else { 
        print("Couldnt get response from \(http)") 
        return 
       } 
       let Result = results[0] as! [String:Any] 
       self.result.append(Result) 
      } 
      catch{ 
       print(error) 
      } 
     } 
    } 
    Info.resume() 

} 
print("finished") 
self.tableView.reloadData() 

如何讓這個我可以刷新我的tableview一旦所有來自請求的數據下載完畢?

回答

0

我認爲最佳的解決方案是使用Operation所以採用這種操作的子類,並請調整headerVal型,我不知道鍵入

import UIKit 

class GetAllData: Operation { 

    //1 
    var headerVal : String = "" //I don't know the type of headerVal 
    var arrayOfDicts : [[String:Any]] = [[:]] 
    var allDataResult : [[String:Any]] = [] 
    var finishedClosure : (([[String:Any]],Error?)->Void)? 
    let sema = DispatchSemaphore(value: 0) 
    var error : Error? 
    //2 
    //I don't know the type of headerVal 
    init(headerVal:String,arrayOfDicts:[[String:Any]]) { 
     super.init() 
     self.arrayOfDicts = arrayOfDicts 
     self.headerVal = headerVal 
    } 

    override func cancel() { 
     self.sema.signal() 
    } 

    override func main() { 
     self.geAllData() 
    } 

    func geAllData() 
    { 
     //4 
     if self.isCancelled { 
      return 
     } 

     for item in self.arrayOfDicts{ 

      let http = item["http"] as! String 
      let URL = NSURL(string: http) 
      let Request = NSMutableURLRequest(url: URL! as URL) 
      Request.setValue(self.headerVal, forHTTPHeaderField: "Authorization") 
      Request.httpMethod = "GET" 
      let UrlSession = URLSession.shared 
      let Info = UrlSession.dataTask(with: Request as URLRequest) { (data, response, error) -> Void in 
       if error != nil{ 
        print(error!) 
       } 
       else{ 
        do{ 
         let ResponseData = try JSONSerialization.jsonObject(with: data!) as! [String:Any] 
         guard let results = ResponseData["data"] as? [Any] else { 
          print("Couldnt get response from \(http)") 
          return 
         } 
         let Result = results[0] as! [String:Any] 
         self.allDataResult.append(Result) 
        } 
        catch{ 
         print(error) 
         self.sema.signal() 
        } 
       } 
       self.sema.signal() 
      } 
      Info.resume() 

      _ = self.sema.wait(timeout: DispatchTime.distantFuture) 
     } 
     print("finished") 

     if(self.finishedClosure != nil) 
     { 
      DispatchQueue.main.async { 
       self.finishedClosure!(self.allDataResult, nil) 
      } 
     } 

     //7 
     if self.isCancelled { 
      return 
     } 

    } 


} 

使用它

self.getAllDataOperation = GetAllData(headerVal: "Your headerVal Here", arrayOfDicts: yourArrayItems) 
     self.getAllDataOperation!.finishedClosure = { [weak self] (results,error) in 
      self?.results = results 
      self?.tableView.reloadData() 
     } 
     let OperationQ = OperationQueue() 
     OperationQ.addOperation(self.getAllDataOperation!) 

希望這有助於,讓我知道如果解決您的問題

0

Sema phore是一種方式,但DispatchGroup可能是更好的方法。

let downloadGroup = DispatchGroup() 
for item in array{ 
    ... 
downloadGroup.enter() 
let Info = UrlSession.dataTask(with: Request as URLRequest) { (data, response, error) -> Void in 
    ... 
    downloadGroup.leave() 
    } 
} 

downloadGroup.notify(queue: DispatchQueue.main) { // 2 
    //callback 
} 
+0

如果我想按順序運行它們,該怎麼辦? – Timeless

+0

然後你應該使用Semaphore作爲上面的示例 – Terence