我正在努力学习如何使用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与此问题无关的源代码也会有所帮助。
谢谢!
答案 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
}
}
}