所以我有一个函数返回一个主题列表,该列表应该通过api返回,但响应闭包仅在函数返回后执行。
我的代码:
func getSectionsList (syllabus_ID: String) -> [String:String] {
var sectionDictionary = [String:String]()
var errorString: String!
let token = Keychain.value(forKey: "Auth_Token")! as String
manager.request(.GET, "\(BASE_URL)/syllabi/\(syllabus_ID)/sections?token=\(token)", encoding:.JSON).validate()
.responseJSON { response in
switch response.result {
case .Success:
let responseJSON = JSON(response.result.value!)
sectionDictionary = self.serializeJSON(responseJSON)
break
case .Failure(let error):
NSLog("Error result: \(error)")
errorString = "\(error)"
return
}
}
return sectionDictionary
}
我尝试使用像这样的完成处理程序:
func getSectionsList (syllabus_ID: String, completionHandler: ([String:String], String?)->()) {
var sectionDictionary = [String:String]()
var errorString: String!
let token = Keychain.value(forKey: "Auth_Token")! as String
manager.request(.GET, "\(BASE_URL)/syllabi/\(syllabus_ID)/sections?token=\(token)", encoding:.JSON).validate()
.responseJSON { response in
switch response.result {
case .Success:
let responseJSON = JSON(response.result.value!)
sectionDictionary = self.serializeJSON(responseJSON)
break
case .Failure(let error):
NSLog("Error result: \(error)")
errorString = "\(error)"
return
}
completionHandler(sectionDictionary, errorString)
}
}
并称之为:
var dictionary = [String:String]()
api.getSectionsList("1"){
(dict, error)in
if dict.count != 0{
dictionary = dict
}
}
所以现在它确实返回了值,但感觉肯定会有更简单的方法吗?是不是有可能只返回我想要的值而不必像我那样实现它的功能?
答案 0 :(得分:2)
不,你已经用封闭(完成处理程序)方法击中了头部。
Alamofire函数.responseJSON()以异步方式返回给您,您还必须通过闭包完成处理程序模式异步返回。
闭包内的任何返回都是闭包本身的返回,而不是闭包周围的范围。
您已将闭包类型定义为
([String:String], String?)->()
为了更好地说明我的观点,AKA与此相同,
[String:String], String?)->Void
这意味着你的闭包不需要返回值(因此是Void),如果你试图这样做,我希望编译器会抱怨。
您将越多地使用此 async 闭包模式。
如果你真的想从你的函数中获得一个返回值,我想你可以使用同步请求使用Alamofire来做这件事虽然我从来没有这样做过,但是我没有理由为你锁定执行周期等待相对缓慢的任务完成。
另外要注意的是你的闭包最初被调用的线程。我相信。如果我没有弄错的话,.responseJSON()将始终在后台线程上返回。所以,假设您希望在请求返回后更新您的UI,如果它不在主线程上,您最终会遇到问题。快速测试会告诉你,
if NSThread.mainThread() == NSThread.currentThread() {
print("ON MAIN THREAD")
} else {
print("NOT ON MAIN THREAD")
}
要确保它在主要部分使用GCD执行此类操作,
dispatch_async(dispatch_get_main_queue(),{
completionHandler(sectionDictionary, errorString)
}