等待下载任务在NSURLSession中完成

问题描述:

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

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

这是我的课与请求功能:

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。

+0

你最终搞清楚了吗? – Mihado

正如我之前在主帖的评论中所说的,下载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); 
} 

这可能不是最有效的,也不是最完美的解决方案,但在我的情况我真的不得不等待下载完成,否则它不应该做任何事情。

+0

在最新夫特: '让旗语= DispatchSemaphore(值:0)'' 然后在URLSession.shared.dataTask' 'semaphore.signal()'' _ = semaphore.wait(超时:DispatchTime.distantFuture )' –