La solicitud api de AlamoFire GET no funciona como se esperaba

Estoy tratando de aprender cómo usar AlamoFire y estoy teniendo problemas.

Mi método hasta ahora es el siguiente:

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 } 

Esto devuelve nada, que es un problema. Según lo que he leído aquí , esto se debe a que la solicitud puede llevar un tiempo, por lo que el cierre no se ejecuta hasta después de la devolución. La solución sugerida de mover el retorno al cierre no funciona para mí y el comstackdor simplemente grita (agregando ->String después (request,response,JSON,error) que da “‘Cadena’ no es un subtipo de vacío”). Lo mismo ocurre con la otra solución provista.

¿Algunas ideas? Incluso algún código fuente que no esté relacionado con este problema, que utilice AlamoFire, sería útil.

¡Gracias!

Una forma de manejar esto es pasar un cierre (generalmente lo llamo un manejador de completionHandler ) a su función Alamofire.request y llamarlo dentro del cierre de 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) } } 

Luego llámalo así (no olvides el manejo de errores):

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

En los comentarios que preguntaste:

Entonces, ¿cómo guardarías la información que recolectaste de la solicitud de obtención si solo puedes hacer cosas dentro del cierre y no afectar objetos fuera del cierre? Además, ¿cómo hacer un seguimiento para saber cuándo ha finalizado la solicitud?

Puede guardar el resultado de la solicitud get en una variable de instancia en su clase desde dentro del cierre; no hay nada en el cierre que te impida hacer eso. Lo que haces desde allí realmente depende de, bueno, qué quieres hacer con esa información.

¿Qué tal un ejemplo?

Dado que parece que está obteniendo un formulario de clave de acceso que recibe la solicitud, tal vez lo necesite para futuras solicitudes realizadas en otras funciones.

En ese caso, puedes hacer algo como esto:

Nota: la progtwigción asincrónica es un tema enorme; demasiado para cubrir aquí. Este es solo un ejemplo de cómo puede manejar los datos que obtiene de su solicitud asincrónica.

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

Con esa configuración, al llamar a somethingNeedingAccessKey() la primera vez se activará una solicitud para obtener la clave de acceso. Cualquier llamada a self._accessKey somethingNeedingAccessKey() después de eso usará el valor ya almacenado en self._accessKey . Si realiza el rest del trabajo de somethingNeedingAccessKey de getAccessKey dentro del cierre que se pasa a getAccessKey , puede estar seguro de que su accessKey siempre será válida. Si necesita otra función que necesite accessKey , simplemente escríbala de la misma manera somethingNeedingAccessKey se escribe accessKey .

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