2015-10-05 54 views
10

我的方案如下所示:我有一個類中有一個函數,該函數向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

回答

11

正如我之前在主帖的評論中所說的,下載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 )' –