【问题标题】:Wait for download task to finish in NSURLSession在 NSURLSession 中等待下载任务完成
【发布时间】:2016-01-02 05:51:05
【问题描述】:

我的场景如下所示:我有一个类,其中包含一个函数,该函数使用 NSURLSession 向服务器发出 POST 请求。在另一个不在该类中的函数中,我使用其中的任务调用该函数,我认为它是异步运行的。我遇到以下问题:当我从服务器下载 JSON 响应并将其写入变量并返回时,我写入的变量仍然为零,因为它没有等待线程/任务完成下载并返回初始值为 nil。

所以我的问题是如何等待该任务完成然后继续整个程序。

这是我的带有请求功能的课程:

class DownloadTask {
var json:NSDictionary!
var cookie:String!
var responseString : NSString = ""

func forData(completion: (NSString) -> ()) {

    var theJSONData:NSData!
    do {
        theJSONData = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions())
    } catch _ {
        print("error")
    }

    let request = NSMutableURLRequest(URL: url)
    request.HTTPMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    if cookie != nil {
        request.setValue(cookie, forHTTPHeaderField: "Cookie")
    }
    request.HTTPBody = theJSONData

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            print("error")
            return
        } else {
            completion(NSString(data: data!, encoding: NSUTF8StringEncoding)!)
        }
    }
    task.resume()
}

}

这是我的调用代码:

let task = DownloadTask()
task.forData { jsonString in
    do {
        if let json: NSDictionary = try NSJSONSerialization.JSONObjectWithData(jsonString.dataUsingEncoding(NSUTF8StringEncoding)!, options:  NSJSONReadingOptions.MutableContainers) as? NSDictionary {
            if json["error"] != nil {
                authenticated = false
            } else {
                let result = json["result"] as! NSDictionary
                user.personId = result["personId"] as! NSNumber
                user.sessionId = result["sessionId"] as! NSString
                print("test0")
                authenticated = true
            }
        }
    }
    catch _ {
        print("error")
    }
}
print("test1")

输出是:

test1
test0

在该任务之后我无法访问变量 user.sessionId。

【问题讨论】:

  • 你最终弄明白了吗?

标签: swift asynchronous nsthread


【解决方案1】:

正如我之前在主帖的 cmets 中所说,下载 NSURLSession.sharedSession().dataTaskWithRequest(request) 与主线程同步运行,这意味着它将数据同步下载到显示。所以简而言之,print("test0") 将在分派线程完成时执行(也就是下载数据)。为了解决这个问题,我不得不使用信号量(我还结合了原始问题中的第一个代码和第二个代码):

private func downloadData(completion: (String) -> ()) {
   let semaphore = dispatch_semaphore_create(0);
   let request = NSMutableURLRequest(URL: url)

   var theJSONData = NSData()
   do {
       theJSONData = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions())
   } catch {
       completion(String())
   }

   request.HTTPMethod = "POST"
   request.setValue("application/json", forHTTPHeaderField: "Content-Type")
   request.HTTPBody = theJSONData

   let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
       data, response, error in
       data == nil ? completion(String()) : completion(String(data: data!, encoding: NSUTF8StringEncoding)!)
       dispatch_semaphore_signal(semaphore);
   }
   task.resume()
   dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}

这可能不是最有效也不是最优雅的解决方案,但就我而言,我真的必须等待下载完成,否则它不应该做任何事情。

【讨论】:

  • 在最新的 Swift 中:let semaphore = DispatchSemaphore(value: 0)then in the URLSession.shared.dataTasksemaphore.signal()_ = semaphore.wait(timeout: DispatchTime.distantFuture)
猜你喜欢
  • 2017-04-14
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多