我的问题与其他几个here非常相似,但我无法让它发挥作用。我通过我写的助手类进行API调用。
首先,我尝试了一个带有返回值的标准函数,结果与预期一致。在累了分配结果后,后台任务就完成了。
现在我使用了一个闭包,我可以将值恢复到我的视图控制器中,但它仍然停留在闭包中,我有同样的问题。我知道我需要使用GCD来使分配在主队列中发生。
这是我在视图控制器中的内容
var artists = [String]()
let api = APIController()
api.getArtistList("foo fighters") { (thelist) -> Void in
if let names = thelist {
dispatch_async(dispatch_get_main_queue()) {
artists = names
print("in the closure: \(artists)")
}
}
}
print ("method 1 results: \(artists)")
结果是:
method 1 results: []
in the closure: [Foo Fighters & Brian May, UK Foo Fighters, John Fogerty with Foo Fighters, Foo Fighters, Foo Fighters feat. Norah Jones, Foo Fighters feat. Brian May, Foo Fighters vs. Beastie Boys]
我知道为什么会这样,我只是不知道如何修复它:( API调用需要异步,那么捕获这些结果的最佳做法是什么?基于用户选择的内容表视图我将进行后续api调用,因此它不像我可以处理闭包内的所有内容
答案 0 :(得分:4)
我完全同意@Craig关于使用GCD的提议,但由于您的问题涉及每次选择行时API调用的请求,您可以执行以下操作:
假设您使用tableView:didSelectRowAtIndexPath:
方法处理选择,然后您可以在其中执行以下操作:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// it is just a form to get the item
let selectedItem = items.objectAtIndex(indexPath.row) as String
api.getArtistList(selectedItem) { (thelist) -> Void in
if let names = thelist {
dispatch_async(dispatch_get_main_queue()) {
artists = names
}
}
}
}
然后你可以在里面观察属性并处理它:
var artists: [String] = [] {
didSet {
self.tableView.reloadData() // or anything you need to handle.
}
}
这只是看待它的另一种方式。我希望这能帮到你。
答案 1 :(得分:1)
简单的解决方案是在你的print()
,内的中做你正在做的任何事情。
由于您已经dispatch_async
到主队列(主/ GUI线程),您可以在那里完成任何处理。推送新的视图控制器,显示一些模态数据,更新当前的视图控制器等。
确保您没有多个线程修改/访问正在显示的本地/缓存数据。特别是如果它被UITableViewDelegate
/ UITableViewDataSource
实现使用,如果你开始变得非常糟糕或与你的返回值不一致,这将会引发契合。
只要您可以在后台检索数据,并且主线程上需要进行的唯一处理是实例变量重新分配,或某种类型的附加,只需执行该操作在主线程上,使用您在后端检索的数据。它并不重。如果 很重,那么您将需要更复杂的同步方法来保护您的数据。
通常情况下,模式如下:
dispatch_async(getBackgroundQueue(), {
var theData = getTheDataFromNetwork();
dispatch_async(dispatch_get_main_queue() {
self.data = theData // Update the instance variable of your ViewController
self.tableView.reloadData() // Or some other 'reload' method
});
})
因此,您通常刷新表视图或通知ViewController操作已完成(或本地数据已更新),您应该继续主线程处理。