我怎么能等到函数从alamofire得到请求的所有数据?
GetData.swift文件:
import Foundation
import Alamofire
import SwiftyJSON
import ObjectMapper
func getStartData() -> Void {
let sharedBranch = BranchSingleton.sharedInstance
let sharedArticle = ArticleSingleton.sharedInstance
Alamofire.request(.GET, Config().apiBranch)
.responseJSON { request, response, result in
let jsonObj = SwiftyJSON.JSON(result.value!)
for obj in jsonObj {
let branch = Mapper<Branch>().map(obj.1.rawString()!)
sharedBranch.addBranch(branch!)
}
}
Alamofire.request(.GET, Config().apiArticle)
.responseJSON { request, response, result in
let jsonObj = SwiftyJSON.JSON(result.value!)
for obj in jsonObj {
let article = Mapper<Article>().map(obj.1.rawString()!)
sharedArticle.addArticle(article!)
}
}
}
ViewController.swift文件:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
getStartData() // need to wait until all requests are finished then do print
print(sharedArticle.articleList)
}
}
SingletonObj.swift文件:
import Foundation
class BranchSingleton {
var branchList: [Branch] = []
class var sharedInstance: BranchSingleton {
struct Static {
static let instance: BranchSingleton = BranchSingleton()
}
return Static.instance
}
func addBranch(branch: Branch) {
branchList.append(branch)
}
}
class ArticleSingleton {
var articleList: [Article] = []
class var sharedInstance: ArticleSingleton {
struct Static {
static let instance: ArticleSingleton = ArticleSingleton()
}
return Static.instance
}
func addArticle(article: Article) {
articleList.append(article)
}
}
我需要等到getStartData()
完成,然后启动单例数组..
我该怎么做呢?
这个getStartData包含超过2个请求,但我只是举了一个例子2.
你问的不是问题。没有理由去"等待"。你也不能。你只需要异步地做你该做的事。同时,接口必须保持活跃;用户必须能够继续工作。因此不需要为"等待"。
现在,如果问题是,当所有的请求都完成后,你如何以一种优雅的方式发送一个信号给你应用的其他部分,一个好的答案是使用NSProgress。所有不同的请求都可以贡献给一个共同的NSProgress对象。好的是它的fractionCompleted
可以用KVO观察到,所以当它大于或等于1.0
时,你就完成了。
但是你实际上不需要NSProgress;您可以对KVO-observable实例变量进行递增或递减操作(当然,要注意线程)。如果您知道有n
进程,那么您可以在n
处启动一个变量,并让每个进程在完成时减少它;当我们达到0时,变量上的didSet
观察者可以采取行动。
关键是:你不需要"等待":你只需要让所有不同的活动对某个共同的中心值做出贡献,该值"知道"何时意味着我们已经"完成",然后可以采取行动。
正如@Matt所说,你不能,也不应该等到Alamofire处理完你的请求。这就像雇人帮你跑腿,然后你停下来,坐在门口等他们回来。你还不如自己去办这件事。
放弃类比,您还不如同步执行任务。然而,同步网络是一个非常糟糕的主意。它冻结UI,直到网络请求完成,如果出现问题,这可能是一个很长的等待。
像Alamofire的request方法这样的异步方法需要一个完成块,一个应该在工作完成时运行的代码块。
请求方法立即返回,甚至在请求发送到服务器之前,更不用说完成了。
与其等待请求完成,不如重构getStartData方法以接受一个完成处理程序,并在工作完成后使用来响应:
func getStartData(completion: () -> void) -> Void {
let sharedBranch = BranchSingleton.sharedInstance
let sharedArticle = ArticleSingleton.sharedInstance
Alamofire.request(.GET, Config().apiBranch)
.responseJSON { request, response, result in
let jsonObj = SwiftyJSON.JSON(result.value!)
for obj in jsonObj {
let branch = Mapper<Branch>().map(obj.1.rawString()!)
sharedBranch.addBranch(branch!)
}
}
Alamofire.request(.GET, Config().apiArticle)
.responseJSON { request, response, result in
let jsonObj = SwiftyJSON.JSON(result.value!)
for obj in jsonObj {
let article = Mapper<Article>().map(obj.1.rawString()!)
sharedArticle.addArticle(article!)
}
//At this point the Alamofire .GET request for Config().apiArticle
//is complete. Call our completion block (passed in as a parameter)
completion()
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
getStartData()
{
//This is a "trailing closure", a block of code passed to getStartData
print("At this point, we've finished getting our data from Alamofire.")
print(sharedArticle.articleList)
}
}
}
注意,您的getStartData
方法在一行中生成2个Alamofire.request()
命令。如果第二个请求要求完成第一个请求,那么您将需要重构该代码,以便第二个Alamofire请求位于第一个调用的完成块中。(这比我现在想做的编辑还要多。)