一尘不染

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

swift

我正在尝试学习如何使用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,这是一个问题。从我在这里阅读的内容来看,这是因为请求可能要花一些时间,因此直到返回之后才执行关闭。建议的将返回值移到闭包中的解决方案对我不起作用,编译器只会大喊大叫(添加->String(request,response,JSON,error)得出的结果是“’String’不是void的子类型”)。提供的其他解决方案也是如此。

有任何想法吗?甚至与该问题无关的某些源代码(使用AlamoFire)也将有所帮助。

谢谢!


阅读 262

收藏
2020-07-07

共1个答案

一尘不染

解决此问题的一种方法是将闭包(通常称为a
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
        }
    }
}
2020-07-07