Alamofire完成工作后如何加载视图?
- 我的问题:
我试图加载数据从服务器,通过Alamofire
之前,SubViewController加载其视图。 在编写代码之后,我没能解决Alamofire的Async Feature的问题。 在Alamofire完成工作之前,视图总是被加载到SubViewController中。
- 部分我的代码:
ParentViewController:
通过PrepareForSegue()
引导到SubViewController的方式。
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "CellDetailSegue" { if let indexPaths = self.dateCollectionView.indexPathsForSelectedItems() { let subViewController = segue.destinationViewController as! SubViewConroller } }
SubViewController:
testing数据是否已经由其viewDidLoad()
print()
中的print()
加载,并通过viewWillAppear()
dataRequest()
加载数据。
class SubViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { var availablePeriods401 = [String]() var availablePeriods403 = [String]() var availablePeriods405 = [String]() override func viewDidLoad() { super.viewDidLoad() self.dataRequest(self.availablePeriods401) self.dataRequest(self.availablePeriods403) self.dataRequest(self.availablePeriods405) print(self.availablePeriods401.count) print(self.availablePeriods403.count) print(self.availablePeriods405.count) } func dataRequest(_ target: [String]) { Alamofire.request(.POST, "http://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON { . . . target = Result } } }
- 问题描述:
加载视图后,SubViewController中的三个variables不能被分配有效值。
三项结果全部为0。
但是如果我在dataRequest()
设置了print()
,我可以得到有效的计数。
- 我的问题:
如何确保Alamofire
完成工作?
我应该把Alamofire请求function放在哪里? viewWillApper()
? viewDidApper()
?
我甚至应该在ParentViewController的PrepareForSegue()
完成请求作业?
请教我如何解决这个问题。
非常感谢您的指导和时间。
伊桑·乔
您应该在viewDidLoad
函数中调用Alamofire请求函数。 当你从完成块(从你打印数据的地方)得到响应时,你应该reload table data
。
你可以像重新加载tableview,
self.tableView.reloadData()
希望这会帮助:)
我注意到的第一件事是你正在做3个asynchronous请求,而不是一个。 你可以使用完成处理程序,但哪一个? 我想你有两个select。
- 嵌套networking电话,以便完成一个开始下一个。 这种方法的缺点是它们将按顺序运行,如果添加更多,则必须继续嵌套。 像这样的方法可能是好的,如果你只打2个电话,但除此之外,它会变得越来越困难。
- 使用信号灯等待所有数据从所有远程调用中加载。 使用完成处理程序来发信号灯。 如果你要使用这种方法,那么它必须在后台线程上完成,因为信号量的使用会阻塞线程,而你不希望主线程发生这种情况。
这三个电话都将同时发生。 即使AlamoFire尚未完成,这些function将会返回。
self.dataRequest(self.availablePeriods401) self.dataRequest(self.availablePeriods403) self.dataRequest(self.availablePeriods405)
无论AlamoFire是否完成,这些都将执行。
print(self.availablePeriods401.count) print(self.availablePeriods403.count) print(self.availablePeriods405.count)
使用信号量看起来像这样:
override func viewWillAppear(animated: Bool) { // maybe show a "Please Wait" dialog? loadMyData() { (success) in // hide the "Please Wait" dialog. // populate data on screen } } func loadMyData(completion: MyCompletionHandler) { // Do this in an operation queue so that we are not // blocking the main thread. let queue = NSOperationQueue() queue.addOperationWithBlock { let semaphore = dispatch_semaphore_create(0) Alamofire.request(.POST, "http://httpbin.org/get", parameters: ["foo": "bar1"]).responseJSON { // This block fires after the results come back // do something dispatch_semaphore_signal(semaphore); } Alamofire.request(.POST, "http://httpbin.org/get", parameters: ["foo": "bar2"]).responseJSON { // This block fires after the results come back // do something dispatch_semaphore_signal(semaphore); } Alamofire.request(.POST, "http://httpbin.org/get", parameters: ["foo": "bar3"]).responseJSON { // This block fires after the results come back // do something dispatch_semaphore_signal(semaphore); } dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) completion(true) } }
Apple Docs – Grand Central Dispatch
如何使用信号量
我给你的问题是,如果有一些,不是所有的networking通话失败,你会怎么做?
首先用false创build一个全局的boolvariables
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "CellDetailSegue" && boolVar { if let indexPaths = self.dateCollectionView.indexPathsForSelectedItems() { let subViewController = segue.destinationViewController as! SubViewConroller } }
使用segue名称调用segue,并从almofire块调用boolVar。