AlamoFire GET API-Anfrage funktioniert nicht wie erwartet

Ich versuche zu lernen, wie man AlamoFire benutzt und ich habe Probleme.

Meine Methode ist wie folgt:

func siteInfo()->String?{ var info:NSDictionary! var str:String! Alamofire.request(.GET, MY_API_END_POINT).responseJSON {(request, response, JSON, error) in info = JSON as NSDictionary str = info["access_key"] as String //return str } return str } 

Dies gibt null zurück, was ein Problem darstellt. Was ich hier gelesen habe , liegt daran, dass die Anfrage eine Weile dauern kann, so dass die Schließung erst nach der Rückkehr ausgeführt wird. Die vorgeschlagene Lösung, den Return in den Closure zu verschieben, funktioniert bei mir nicht und der Compiler schreit nur (addieren ->String nach (request,response,JSON,error) was “‘String’ ist kein Untertyp von void”). Gleiches gilt für die andere zur Verfügung gestellte Lösung.

Irgendwelche Ideen? Selbst ein Quellcode, der nicht mit diesem Problem zusammenhängt und AlamoFire verwendet, wäre hilfreich.

Vielen Dank!

   

Eine Möglichkeit, dies zu umgehen, besteht darin, eine Closure (normalerweise einen completionHandler ) an Ihre siteInfo function zu übergeben und diese innerhalb von Alamofire.request :

 func siteInfo(completionHandler: (String?, NSError?) -> ()) -> () { Alamofire.request(.GET, MY_API_END_POINT).responseJSON { (request, response, JSON, error) in let info = JSON as? NSDictionary // info will be nil if it's not an NSDictionary let str = info?["access_key"] as? String // str will be nil if info is nil or the value for "access_key" is not a String completionHandler(str, error) } } 

Dann nenne es so (Fehlerbehandlung nicht vergessen):

 siteInfo { (str, error) in if str != nil { // Use str value } else { // Handle error / nil value } } 

In den Kommentaren haben Sie gefragt:

Wie würden Sie also die Informationen speichern, die Sie von der Get-Anfrage sammeln, wenn Sie nur Dinge innerhalb der Schließung tun können und keine Objekte außerhalb der Schließung bearbeiten? Wie kann man wissen, wann die Anfrage beendet ist?

Sie können das Ergebnis der Abrufanforderung in einer Instanzvariablen in Ihrer class speichern, die sich innerhalb der Closure befindet. Es gibt nichts an der Schließung, die dich daran hindert, das zu tun. Was Sie da tun, hängt wirklich davon ab, was Sie mit diesen Daten machen wollen.

Wie wäre es mit einem Beispiel?

Da es so aussieht, als ob Sie ein Zugriffsschlüsselformular erhalten, das eine Anfrage erhält, brauchen Sie das vielleicht für zukünftige Anfragen, die in anderen functionen gestellt werden.

In diesem Fall können Sie Folgendes tun:

Hinweis: Asynchrones Programmieren ist ein großes Thema. viel zu viel, um hier zu sehen. Dies ist nur ein Beispiel dafür, wie Sie mit den Daten umgehen können, die Sie von Ihrer asynchronen Anfrage erhalten haben.

 public class Site { private var _accessKey: String? private func getAccessKey(completionHandler: (String?, NSError?) -> ()) -> () { // If we already have an access key, call the completion handler with it immediately if let accessKey = self._accessKey { completionHandler(accessKey, nil) } else { // Otherwise request one Alamofire.request(.GET, MY_API_END_POINT).responseJSON { (request, response, JSON, error) in let info = JSON as? NSDictionary // info will be nil if it's not an NSDictionary let accessKey = info?["access_key"] as? String // accessKey will be nil if info is nil or the value for "access_key" is not a String self._accessKey = accessKey completionHandler(accessKey, error) } } } public func somethingNeedingAccessKey() { getAccessKey { (accessKey, error) in if accessKey != nil { // Use accessKey however you'd like here println(accessKey) } else { // Handle error / nil accessKey here } } } } 

Bei diesem Setup wird beim ersten Aufruf von somethingNeedingAccessKey() eine Anfrage ausgetriggers, um den Zugriffsschlüssel zu erhalten. Alle Aufrufe von somethingNeedingAccessKey() danach verwenden den Wert, der bereits in self._accessKey gespeichert self._accessKey . Wenn Sie den Rest von somethingNeedingAccessKey getAccessKey ‘s Arbeit in der Schließung an getAccessKey , können Sie sicher sein, dass Ihr accessKey immer gültig sein wird. Wenn Sie eine andere function benötigen, die accessKey benötigt, schreiben Sie sie einfach auf die gleiche Art und Weise wie accessKey geschrieben wird.

 public func somethingElse() { getAccessKey { (accessKey, error) in if accessKey != nil { // Do something else with accessKey } else { // Handle nil accessKey / error here } } }