2015-10-05 15 views
10

Mein Szenario sieht so aus: Ich habe eine Klasse, die eine Funktion hat und diese Funktion macht eine POST-Anfrage an einen Server mit NSURLSession. In einer anderen Funktion, die nicht in dieser Klasse ist, rufe ich diese Funktion mit der Aufgabe darin auf, die asynchron abläuft, denke ich. Ich habe folgendes Problem: Wenn ich die JSON-Antwort vom Server herunterlade und sie in eine Variable schreibe und sie zurückschicke, ist die Variable, in die ich geschrieben habe, immernoch null, da sie nicht darauf gewartet hat, dass der Thread/Task den Download beendet und gibt den Anfangswert zurück, der Null ist.Warte, bis Download-Aufgabe in NSURLSession fertig ist

Also meine Frage ist, wie kann ich auf diese Aufgabe warten, um zu beenden und dann das ganze Programm fortzusetzen.

Das ist meine Klasse mit der Anfrage-Funktion:

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

}

Und das ist meine Berufung Code:

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

Die Ausgabe lautet:

test1 
test0 

Und ich kann nicht ass ss die Variablen user.sessionId nach dieser Aufgabe.

+0

Haben Sie es herausgefunden? – Mihado

Antwort

11

Wie ich schon sagte in den Kommentaren des Hauptbeitrags der Download NSURLSession.sharedSession().dataTaskWithRequest(request) laufen synchron zum Haupt-Thread, was bedeutet, dass es die Daten synchron zur Anzeige herunterlädt. Kurz gesagt, die print("test0") wird ausgeführt, wenn der gesendete Thread beendet ist (auch bekannt als Download der Daten). Um dies zu beheben ich Semaphore verwenden musste (I kombiniert auch den ersten Code und der zweite Code aus der ursprünglichen Frage):

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); 
} 

Dies mag nicht die effizienteste noch die eleganteste Lösung, aber in meinem Fall habe ich wirklich musste warten, bis das Herunterladen beendet war, sonst sollte es nichts tun.

+0

In der aktuellen Swift: 'lassen Semaphore = DispatchSemaphore (Wert: 0)' ' dann in dem URLSession.shared.dataTask' ' semaphore.signal() '' _ = semaphore.wait (Timeout: DispatchTime.distantFuture) ' –

Verwandte Themen