Alamofire 完成工作后如何加载视图?
Posted
技术标签:
【中文标题】Alamofire 完成工作后如何加载视图?【英文标题】:How to load view after Alamofire finished its job? 【发布时间】:2016-04-28 09:57:05 【问题描述】: 我的问题:我正在尝试在 SubViewController 加载其视图之前通过 Alamofire
从服务器加载数据。写完代码,没能解决Alamofire的Async Feature的问题。在 Alamofire 完成工作之前,视图总是被加载到 SubViewController 中。
父视图控制器:
通过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
子视图控制器:
测试其viewDidLoad()
中的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 中的三个变量分配有效值。
三个输出的结果都是0。
但如果我在dataRequest()
中设置print()
,我可以获得有效计数。
如何确保Alamofire
完成其工作?
我应该把 Alamofire 请求函数放在哪里? viewWillApper()
? viewDidApper()
?
我应该在 ParentViewController 的PrepareForSegue()
中完成请求工作吗?
请教我如何解决这个问题。
非常感谢您的指导和时间。
伊桑乔
【问题讨论】:
【参考方案1】:您应该在 viewDidLoad
函数中调用 Alamofire 请求函数。当您收到完成块的响应(从您打印数据的位置)时,您应该reload table data
。
你可以像这样重新加载tableview,
self.tableView.reloadData()
希望这会有所帮助:)
【讨论】:
首先,感谢您的回答。我有一个问题:我不确定每次拨打reloadData()
时是否会涉及viewDidLoad()
。我的意思是,viewDidLoad()
将在视图加载时被调用一次。也许您的意思是在viewWillAppear()
中设置reloadData()
?
在完成处理程序中获得响应时,方法中没有重新加载数据。不知道它在 swift 中调用了什么,但它是完成处理程序,仅在您获得响应后才会调用,因此在获得完整响应后重新加载表数据,以便相应地重新加载表视图。【参考方案2】:
我注意到的第一件事是您正在执行 3 个异步请求,而不是一个。您可以使用完成处理程序,但哪个?我认为你有两个选择。
-
嵌套网络调用,以便完成一个调用开始下一个调用。这种方法的缺点是它们将按顺序运行,如果添加更多,则必须继续嵌套。如果您只进行 2 次调用,这样的方法可能没问题,但除此之外,它会变得越来越困难。
使用信号量等待所有远程调用的所有数据都加载完毕。使用完成处理程序向信号量发出信号。如果您要使用这种方法,则必须在后台线程上完成,因为使用信号量会阻塞线程,您不希望在主线程上发生这种情况。
这三个调用将同时发生。即使 AlamoFire 没有完成,函数也会返回。
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
How to use semaphores
我要问你的问题是,如果一些,不是所有的网络调用都失败了,你会怎么做?
【讨论】:
感谢您的回答。问题解决了。【参考方案3】:先用false创建一个全局bool变量
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 名称和 boolVar true 从 almofire 块调用 prepare segue。
【讨论】:
感谢您的回答和时间。我有一个问题:假设一种情况,我按下一个按钮或其他东西来从 ParentViewController 转换到 SubViewController,这意味着它将调用prepareForSegue()
。好吧,如果boolVar
是false
当我触发此转换时,您的解决方案会起作用吗(恕我直言!!!)?视图会在 Alamofire 获取其数据之前被冻结,还是我需要在 Alamofire 获取其数据时按下按钮触发转换?
这个答案没有意义。以上是关于Alamofire 完成工作后如何加载视图?的主要内容,如果未能解决你的问题,请参考以下文章
加载远程数据后 swift alamofire 显示视图控制器
从 alamofire swift 的 tableview 单元格中的 url 加载图像