2016-03-19 8 views
0

Im Allgemeinen ist es erforderlich, eine Klasse für das Netzwerk zu implementieren. Dies ist eine Klasse, die eine URL annimmt und Daten gibt. All dies wird getan, um keine zusätzlichen Logiksteuerungen zu erzielen. Ich habe ein Problem festgestellt, dass beim Erstellen einer Ansicht die Daten nicht angezeigt werden. Das ist Network Klasse:NSURLSession gibt keine Daten im ersten Aufruf zurück

private static var dataTask: NSURLSessionDataTask? 

private static var dataJSON: NSData? 

private static var sessionConfig: NSURLSessionConfiguration = { 
    var configuration = NSURLSessionConfiguration.defaultSessionConfiguration() 
    configuration.allowsCellularAccess = false 
    configuration.HTTPMaximumConnectionsPerHost = 2 
    configuration.HTTPAdditionalHeaders = ["Accept": "application/json"] 
    configuration.timeoutIntervalForRequest = 30.0 
    configuration.timeoutIntervalForResource = 60.0 
    return configuration 
}() 


static func getListObjectsBy(url: String?) -> NSData? { 
    let session = NSURLSession(configuration: sessionConfig) 
    log.debug("DataTask start") 
    dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { (data, response, error) in 
     log.debug("if error = error") 
     if let error = error { 
      print(error.localizedDescription) 
     } else if let httpResponse = response as? NSHTTPURLResponse { 
      log.debug("if httpResponse") 
      if httpResponse.statusCode == 200 { 
       dataJSON = data 
      } else { 
       print("Bad request") 
      } 
     } 
    } 
    dataTask?.resume() 
    log.debug("DataTask Resume") 
    return dataJSON 
} 

Methode viewDidLoad in meinem Haupt-Controller:

let response = Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5") 
print(String(response)) 

Mein log sagen mir, dass die Daten Rückkehr gleich Null. Notizen, ich bin zwischen den Controllern mit Hilfe SWRevealViewController wechseln. Beim erneuten Laden des Hauptansicht-Controllers werden die Daten zurückgegeben. Was ich mache?

enter image description here

Antwort

1

Sie scheinen Missverständnis zu sein, dass dies ein asynchroner Aufruf ist.

static func getListObjectsBy(url: String?) -> NSData? { 
    let session = NSURLSession(configuration: sessionConfig) 
    log.debug("DataTask start") 
    dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { (data, response, error) in 
     // Everything in this block is happening on a separate thread. 
     log.debug("if error = error") 
     if let error = error { 
      print(error.localizedDescription) 
     } else if let httpResponse = response as? NSHTTPURLResponse { 
      log.debug("if httpResponse") 
      if httpResponse.statusCode == 200 { 
       // this won't happen until the data comes back from the remote call. 
       dataJSON = data 
      } else { 
       print("Bad request") 
      } 
     } 
    } 
    // This code here does not wait for the response from the remote. 
    // The call to the remote is sent then this code 
    // is immediately executed WITHOUT WAITING 
    dataTask?.resume() 
    log.debug("DataTask Resume") 
    // dataJSON will be nil until the remote answers. 
    return dataJSON 
} 

Wenn Sie dies tun:

let response = Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5") 
print(String(response)) 

Die Fernbedienung noch nicht beantwortet hat, so dass Sie gleich Null bekommen.

Ihre nächste Frage könnte sein: "Was mache ich dagegen?". Die Antwort ist nicht klar, ohne alles andere zu wissen, was Sie tun.

Themen

Mehrere Threads der Ausführung ist wie zwei Programme gleichzeitig laufen. Denken Sie an 2 Personen, die gleichzeitig an zwei verschiedenen Aufgaben arbeiten. Um die Benutzeroberfläche sehr reaktionsschnell zu halten, verwendet iOS einen Ausführungs-Thread zur Aktualisierung des Bildschirms. Wenn ein Prozess ausgeführt werden muss, der lange dauert, möchten wir nicht, dass der Bildschirm wartet, bis dies erledigt ist. Angenommen, Sie müssen Daten von einem Remote-System abrufen, und dieses Remote-System ist langsam. Ihr Gerät würde dort erstarren, bis die Antwort zurückkommt. Um dies zu vermeiden, werden Aktivitäten wie Aufrufe von Remote-Systemen in einem anderen Thread ausgeführt. Die Anforderung wird an das Betriebssystem selbst gesendet und das Betriebssystem wird aufgefordert, zurückzurufen, wenn die Operation abgeschlossen ist.

Dies ist, was hier passiert.
Richtet die Anforderung zum Senden an das Betriebssystem ein.

Trifft das Betriebssystem auf, um mit der Arbeit zu beginnen.

dataTask?.resume() 

Dieser Block ist der Rückruf AKA der Schließung. iOS wird diesen Code ausführen, wenn der Remoteanruf abgeschlossen ist.

dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { 
    // Closure starts here 
    // Gets called when the remote has sent a response. 
    (data, response, error) in 
    // Everything in this block is happening on a separate thread. 
    log.debug("if error = error") 
    etc 
} 

Das bedeutet, dass Sie warten müssen, bis die Antwort zurückkommt, bevor Sie Ihre Ausgabe drucken. Sie können dazu in Ihrer Funktion eine Closure verwenden.

public typealias CompletionHandler = (data: NSData?, error: NSError?) -> Void 

static func getListObjectsBy(url: String?, completion: CompletionHandler) { 
    let session = NSURLSession(configuration: sessionConfig) 
    log.debug("DataTask start") 
    dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { 
     (data, response, error) in 
     // Everything in this block is happening on a separate thread. 
     log.debug("if error = error") 
     if let error = error { 
      print(error.localizedDescription) 
     } else if let httpResponse = response as? NSHTTPURLResponse { 
      log.debug("if httpResponse") 
      if httpResponse.statusCode == 200 { 
       // this won't happen until the data comes back from the remote call. 
      } else { 
       print("Bad request") 
      } 
     } 
     // Call your closure 
     completion(data, error) 
    } 
    // This code here does not wait for the response from the remote. 
    // The call to the remote is sent then this code 
    // is immediately executed WITHOUT WAITING 
    dataTask?.resume() 
    log.debug("DataTask Resume") 
} 

In Ihrem Telefonvorwahl würden Sie dies tun:

Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5") { 
    (data, error) in 
    if let data == data { 
     print(data) 
    } 
} 
+0

ich etwas nicht tun, sonst :) Alles Code. Leider verstehe ich nicht wirklich, wann asynchronen Versand zu verwenden ist. Was mache ich dagegen? –

+0

Ich denke, Ihre Antwort ist richtig, aber Sie können ein wenig mehr über die Verwendung von Schließungen, um die Daten in der asynchronen Anruf weiter zu helfen, um die Frage –

+0

Vielen Dank! Jetzt verstehe ich alles! :) –

Verwandte Themen