【发布时间】:2017-01-12 09:04:46
【问题描述】:
我正在使用 HanekeSwift 检索缓存的数据,然后在每次视图出现时将其设置为 swipeView 中的标签。我的代码检索数据没有问题,但是因为cache.fetch()是异步的,所以当我调用我的方法更新视图时,我的标签设置为nil。无论如何要告诉 swift 在加载视图之前等到我的缓存数据被检索到?
见下面的代码:
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)
}
}
当我单步执行上述代码时,它总是显示视图,然后单步进入缓存块。如何使 viewWillAppear() 允许 updateEntries() 完成并且在执行缓存块之前不返回它?提前致谢!
更新 1:
下面的解决方案运行良好,我的调用以正确的顺序进行(我在通知块中的打印语句在缓存检索后执行),但我的视图仅在服务器运行时使用非零值更新它们的标签叫。也许我在通知组中混入了错误的代码?
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:
另外,当我切换视图时,我会在控制台中收到此警告。我想我用上面的代码锁定了主线程
“此应用程序正在从后台线程修改自动布局引擎,这可能导致引擎损坏和奇怪的崩溃。这将在未来的版本中导致异常。”
【问题讨论】:
-
你不应该阻塞主线程,因为它负责将 UI 组件绘制到屏幕上并处理用户与它们的交互。您应该让您的 UI 功能齐全,并在没有数据时看起来正常。
-
@ozgur 明白了。那么这是否意味着一旦我检索到该数据,那么我应该刷新视图?我尝试在我的 swipeView 中重新加载数据,但似乎没有解决问题
-
是的,如果你的 UI 依赖于显示来自远程资源的一些内容,基本流程是这样的:你通过显示一些加载指示器来禁用用户交互,调用检索内容,然后更新您的数据源控制内容并重新加载 UI。
-
@ozgur 好的,那么我将如何设置加载屏幕以等待按此顺序检索数据 1. viewLoads 和加载屏幕出现 2. 加载屏幕出现 3. 缓存或服务器被调用检索数据 4. 视图设置为值 5. 加载屏幕被移除 目前,加载屏幕不会等到数据被检索到才会被移除,因为事情是异步发生的
-
在类似的问题中,我读到我需要使用完成处理程序来允许显示数据。这个问题是不是这样,如果是这样,有人可以提供一个如何解决这个问题的例子吗?
标签: swift asynchronous closures grand-central-dispatch haneke