我使用 HanekeSwift 检索缓存的数据,然后在每次 View 出现时将其设置为 swipeView 中的标签。我的代码检索数据没有问题,但由于 cache.fetch()
是异步的,当我调用我的方法来更新 View 时,我的标签被设置为 nil
。无论如何,有没有办法告诉 swift 在加载 View 之前等待我的缓存数据被检索?
参见下面的代码:
override func viewWillAppear(animated: Bool) {
updateEntries() // updates entries from cache when view appears
}
func updateEntries() {
guard let accessToken = NSUserDefaults.standardUserDefaults().valueForKey("accessToken") as? String else { return }
guard let cachedEntryKey = String(accessToken) + "food_entries.get" as? String else { return }
cache.fetch(key: cachedEntryKey).onSuccess { data in
...
// if successful, set labels in swipeView to data retrieved from cache
...
dispatch_group_leave(dispatchGroup)
} .onFailure { error in
print(error)
...
// if unsuccessful, call servers to retrieve data, set labels in swipeView to that data
...
dispatch_group_leave(dispatchGroup)
}
}
当我单步执行上面的代码时,它总是显示 View ,然后单步进入缓存 block 。如何使 viewWillAppear() 允许 updateEntries() 完成并且在执行缓存 block 之前不返回?提前非常感谢!
更新1:
下面的解决方案工作得很好,我的调用是按正确的顺序进行的(通知 block 中的打印语句在缓存检索后执行),但我的 View 仅在服务器启动时用非零值更新其标签叫。也许我在通知组中添加了错误的代码?
override func viewWillAppear(animated: Bool) {
self.addProgressHUD()
updateEntries() // updates entries from cache when view appears
}
func updateEntries() {
guard let accessToken = NSUserDefaults.standardUserDefaults().valueForKey("accessToken") as? String else { return }
guard let cachedEntryKey = String(accessToken) + "food_entries.get" as? String else { return }
let dispatchGroup = dispatch_group_create()
dispatch_group_enter(dispatchGroup)
dispatch_group_async(dispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
cache.fetch(key: cachedEntryKey).onSuccess { data in
...
// if successful, set labels in swipeView to data retrieved from cache
...
} .onFailure { error in
print(error)
...
// if unsuccessful, call servers to retrieve data, set labels in swipeView to that data
...
}
}
dispatch_group_notify(dispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
print("Retrieved Data")
self.removeProgressHUD()
}
}
更新2:
此外,当我切换 View 时,我在控制台中收到此警告。我想我用上面的代码锁定了主线程
“此应用程序正在从后台线程修改自动布局引擎,这可能会导致引擎损坏和奇怪的崩溃。这将在将来的版本中导致异常。”
最佳答案
注意:
- 调用异步方法之前进入组
- 离开组是每个相应的完成/失败处理程序
- 将通知 block 中的 UI 更新调度到主队列
因此:
func updateEntries() {
guard let accessToken = NSUserDefaults.standardUserDefaults().valueForKey("accessToken") as? String else { return }
guard let cachedEntryKey = String(accessToken) + "food_entries.get" as? String else { return }
let group = dispatch_group_create()
dispatch_group_enter(group)
cache.fetch(key: cachedEntryKey).onSuccess { data in
...
// if successful, set labels in swipeView to data retrieved from cache
...
dispatch_group_leave(group)
} .onFailure { error in
print(error)
...
// if unsuccessful, call servers to retrieve data, set labels in swipeView to that data
...
dispatch_group_leave(group)
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("Retrieved Data")
self.removeProgressHUD()
}
}
关于Swift:在 View 出现之前从异步调用中检索值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39323035/