AlamoFire GET api 请求未按预期工作

Posted

技术标签:

【中文标题】AlamoFire GET api 请求未按预期工作【英文标题】:AlamoFire GET api request not working as expected 【发布时间】:2014-09-17 22:37:57 【问题描述】:

我正在尝试学习如何使用 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 来看,这是因为请求可能需要一段时间,所以闭包直到返回之后才会执行。将返回移动到闭包中的建议解决方案对我不起作用,编译器只是大喊大叫(在(request,response,JSON,error) 之后添加->String,这给出了“'String' 不是 void 的子类型”)。提供的其他解决方案也是如此。

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

谢谢!

【问题讨论】:

你能弄清楚如何在没有完成处理程序的情况下使用 alamofire 返回数据吗? 【参考方案1】:

处理此问题的一种方法是将闭包(我通常称之为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
    


在您询问的 cmets 中:

那么,如果您保存从 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 中的值。如果您在传递给getAccessKey 的闭包内完成somethingNeedingAccessKey 的其余工作,您可以确定您的accessKey 将始终有效。如果您需要另一个需要accessKey 的函数,只需按照somethingNeedingAccessKey 的编写方式编写即可。

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

【讨论】:

你不会在这里遇到同样的问题吗?例如var stuff:String! siteInfo str in stuff = str println(stuff) 打印为零 是的,但是您并没有真正正确地使用异步函数。您需要在闭包内完成 siteInfo 函数(如 println)之后必须完成的所有事情。 那么,如果您只能在闭包内执行操作而不影响闭包外的对象,您将如何保存从 get 请求中收集的信息?很抱歉提出了一些愚蠢的问题,但我有点困惑。 我用一个例子更新了答案。这可能不是您想要做的,但希望它会为您指明正确的方向。 这似乎在设计应用程序和 api 时会很快变得复杂。你知道关于这个主题(异步和同步请求)你会推荐的任何书籍吗?感谢您的回复!

以上是关于AlamoFire GET api 请求未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

Angular HTTP GET 请求未按预期工作

AWS API Gateway 限制未按预期工作

从 .Net 应用程序到 AWS API Gateway 的 HTTP POST 请求未按预期工作

Fusion Auth /api/jwt/issue api 未按预期工作

带参数的 Alamofire 4 Swift 3 GET 请求

Client.guilds.get() 未按预期工作