【问题标题】:(Swift) Using semaphore with a NSURLSession in a for loop(Swift) 在 for 循环中使用带有 NSURLSession 的信号量
【发布时间】:2017-07-12 16:02:33
【问题描述】:

我目前正在尝试从 for 循环中的多个 GET 请求中下载数据,然后将其添加到表视图中。 我成功地获取了数据,但我遇到的问题是主线程在从请求中下载所有数据之前一直在运行,因此它没有加载到表视图中。 我正在尝试使用信号量尝试一次运行一个线程,但它似乎不起作用。 代码如下:

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

如何在请求中的所有数据下载完成后刷新表格视图?

【问题讨论】:

    标签: ios swift semaphore nsurlsession


    【解决方案1】:

    信号量是一种方式,但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
     }   
    

    【讨论】:

    • 如果我想按顺序运行它们怎么办?
    • 那么你应该使用 Semaphore 作为上面的示例
    【解决方案2】:

    我认为最佳解决方案是使用Operation所以使用这个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!)
    

    希望对您有所帮助,如果解决了您的问题,请告诉我

    【讨论】:

      猜你喜欢
      • 2016-09-07
      • 1970-01-01
      • 2017-02-06
      • 2013-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-21
      相关资源
      最近更新 更多