Solicitação de API GAM do AlamoFire não está funcionando como esperado

Estou tentando aprender como usar o AlamoFire e estou com problemas.

Meu método até agora é o seguinte:

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 } 

Isso retorna nada, o que é um problema. Pelo que li aqui , isso acontece porque o pedido pode demorar um pouco para que o fechamento não seja executado até depois do retorno. A solução sugerida de mover o retorno para o encerramento não funciona para mim e o compilador apenas grita (adicionando ->String após (request,response,JSON,error) que dá “‘String’ não é um subtipo de void”). O mesmo vale para a outra solução fornecida.

Alguma ideia? Até mesmo algum código-fonte que não esteja relacionado a esse problema, que usa o AlamoFire, seria útil.

Obrigado!

Uma maneira de lidar com isso é passar um encerramento (normalmente eu chamo de completionHandler ) para a sua function siteInfo e chamar isso dentro do fechamento do 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) } } 

Então ligue assim (não esqueça de manipular erros):

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

Nos comentários que você perguntou:

Então, como você salvaria as informações coletadas da solicitação get se pudesse fazer apenas coisas dentro do fechamento e não afetar objects fora do fechamento? Além disso, como acompanhar para saber quando a solicitação foi concluída?

Você pode salvar o resultado da solicitação get em uma variável de instância em sua class de dentro do fechamento; Não há nada sobre o encerramento impedindo você de fazer isso. O que você faz de lá realmente depende, bem, do que você quer fazer com esses dados.

Como sobre um exemplo?

Como parece que você está recebendo um formulário de chave de access que recebe uma solicitação, talvez você precise disso para solicitações futuras feitas em outras funções.

Nesse caso, você pode fazer algo assim:

Nota: A programação assíncrona é um tópico enorme; demais para cobrir aqui. Este é apenas um exemplo de como você pode manipular os dados que recebe de sua solicitação assíncrona.

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

Com essa configuração, chamar somethingNeedingAccessKey() pela primeira vez acionará uma solicitação para obter a chave de access. Qualquer chamada para somethingNeedingAccessKey() depois disso, usará o valor já armazenado em self._accessKey . Se você fizer o resto do trabalho de somethingNeedingAccessKey dentro do fechamento sendo passado para getAccessKey , você pode ter certeza que seu accessKey sempre será válido. Se você precisar de outra function que precise de accessKey , apenas escreva-a da mesma forma que somethingNeedingAccessKey é escrito.

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