AlamoFire GET api 请求未按预期工作 [英] AlamoFire GET api request not working as expected

查看:26
本文介绍了AlamoFire GET api 请求未按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力学习如何使用 AlamoFire,但遇到了问题.

目前我的方法如下:

func siteInfo()->String?{变量信息:NSDictionary!var str:字符串!Alamofire.request(.GET, MY_API_END_POINT).responseJSON {(request, response, JSON, error) ininfo = JSON 作为 NSDictionarystr = info["access_key"] 作为字符串//返回字符串}返回字符串}

这会返回 nil,这是一个问题.根据我在此处的阅读,这是因为请求可能需要一段时间,因此关闭不会直到返回后才执行.将返回移动到闭包中的建议解决方案对我不起作用,编译器只是大喊大叫(在 (request,response,JSON,error) 之后添加 ->String这给出了'String' 不是 void 的子类型").提供的其他解决方案也是如此.

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

谢谢!

解决方案

处理这个问题的一种方法是将闭包(我通常称之为 completionHandler)传递给你的 siteInfocode> 函数并在 Alamofire.request 的闭包中调用它:

func siteInfo(completionHandler: (String?, NSError?) -> ()) ->(){Alamofire.request(.GET, MY_API_END_POINT).responseJSON {(请求、响应、JSON、错误)中让信息 = JSON 作为?NSDictionary//如果不是 NSDictionary,则信息将为 nil让 str = info?["access_key"] 作为?String//如果 info 为 nil 或access_key"的值不是 String,则 str 将为 nil完成处理程序(字符串,错误)}}

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

siteInfo { (str, error) in如果 str != nil {//使用str值} 别的 {//处理错误/nil 值}}

<小时>

在您提出的评论中:

<块引用>

如果你从 get 请求中收集到的信息,你将如何保存?只能在闭包内部做事,而不能影响外部的对象关闭?此外,如何跟踪以了解请求何时完成了吗?

您可以从闭包内部将获取请求的结果保存到您的类中的实例变量中;关闭并没有阻止你这样做.你从那里做什么实际上取决于你想用这些数据做什么.

举个例子怎么样?

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

在这种情况下,您可以执行以下操作:

注意:异步编程是一个巨大的话题;太多了,无法在这里介绍.这只是您如何处理从异步请求中返回的数据的一个示例.

公共类站点{私有变量_accessKey:字符串?private func getAccessKey(completionHandler: (String?, NSError?) -> ()) ->(){//如果我们已经有一个访问密钥,立即用它调用完成处理程序如果让 accessKey = self._accessKey {完成处理程序(访问密钥,零)} else {//否则请求一个Alamofire.request(.GET, MY_API_END_POINT).responseJSON {(请求、响应、JSON、错误)中让信息 = JSON 作为?NSDictionary//如果不是 NSDictionary,则信息将为 nil让 accessKey = info?["access_key"] 作为?String//如果 info 为 nil 或access_key"的值不是 String,accessKey 将为 nilself._accessKey = accessKey完成处理程序(访问密钥,错误)}}}public func somethingNeedingAccessKey() {getAccessKey { (accessKey, error) in如果访问密钥 != nil {//在这里随意使用 accessKey打印(访问密钥)} 别的 {//在这里处理错误/nil accessKey}}}}

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

public func somethingElse() {getAccessKey { (accessKey, error) in如果访问密钥 != nil {//用 accessKey 做其他事情} 别的 {//在这里处理 nil accessKey/错误}}}

I am trying to get learn how to use AlamoFire and I am having trouble.

My method so far is as follows:

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
}

This returns nil which is a problem. From what I have read here, this is because the request can take a while so the closure doesn't execute till after the return. The suggested solution of moving the return into the closure does not work for me and the compiler just yells (adding ->String after (request,response,JSON,error) which gives "'String' is not a subtype of void"). Same goes for the other solution provided.

Any ideas? Even some source code that is not related to this problem, that uses AlamoFire, would be helpful.

Thanks!

解决方案

One way to handle this is to pass a closure (I usually call it a completionHandler) to your siteInfo function and call that inside Alamofire.request's closure:

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

Then call it like this (don't forget error handling):

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


In the comments you asked:

So how would you save the info you collect from the get request if you can only do stuff inside the closure and not effect objects outside of the closure? Also, how to keep track to know when the request has finished?

You can save the result of the get request to an instance variable in your class from inside the closure; there's nothing about the closure stopping you from doing that. What you do from there really depends on, well, what you want to do with that data.

How about an example?

Since it looks like you're getting an access key form that get request, maybe you need that for future requests made in other functions.

In that case, you can do something like this:

Note: Asynchronous programming is a huge topic; way too much to cover here. This is just one example of how you might handle the data you get back from your asynchronous request.

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

With that setup, calling somethingNeedingAccessKey() the first time will trigger a request to get the access key. Any calls to somethingNeedingAccessKey() after that will use the value already stored in self._accessKey. If you do the rest of somethingNeedingAccessKey's work inside the closure being passed to getAccessKey, you can be sure that your accessKey will always be valid. If you need another function that needs accessKey, just write it the same way somethingNeedingAccessKey is written.

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

这篇关于AlamoFire GET api 请求未按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆