AlamoFire GET api请求无法按预期工作

时间:2014-09-17 22:37:58

标签: swift alamofire

我正在努力学习如何使用AlamoFire而我遇到了麻烦。

到目前为止我的方法如下:

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
}

这会返回nil,这是一个问题。从我所读的here开始,这是因为请求可能需要一段时间才能在返回之前执行闭包。将返回值移动到闭包中的建议解决方案对我来说不起作用,编译器只是大喊(在->String之后添加(request,response,JSON,error),这使得''String'不是void的子类型“)。同样适用于所提供的其他解决方案。

有什么想法吗?即使是一些使用AlamoFire与此问题无关的源代码也会有所帮助。

谢谢!

1 个答案:

答案 0 :(得分:31)

处理此问题的一种方法是将一个闭包(我通常将其称为completionHandler)传递给siteInfo函数,并在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)
    }
}

然后像这样调用它(不要忘记错误处理):

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

在评论中你问:

  

那么如果你如何保存从get请求中收集的信息呢?   只能在闭包内做东西而不影响外面的对象   封闭?此外,如何跟踪以了解请求何时具有   完成了吗?

您可以从闭包内部将get请求的结果保存到类中的实例变量中;封闭阻止你做这件事没有任何关系。你从那里做什么真的取决于你想用这些数据做什么。

一个例子怎么样?

由于看起来您正在获取获取请求的访问密钥表单,因此您可能需要将其用于将来在其他功能中发出的请求。

在这种情况下,你可以这样做:

注意:异步编程是一个很大的主题;太多了,无法覆盖这里。这只是您如何处理从异步请求中获取的数据的一个示例。

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

使用该设置,第一次调用somethingNeedingAccessKey()将触发获取访问密钥的请求。之后对somethingNeedingAccessKey()的任何调用都将使用已存储在self._accessKey中的值。如果您将somethingNeedingAccessKey的其余工作内容传递到getAccessKey,那么您可以确保accessKey始终有效。如果您需要另一个需要accessKey的函数,只需按照写somethingNeedingAccessKey的方式编写它。

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