我正在为一个app项目编写一个简单的缓存框架,并在Closures中使用GCD和DispatchQueues来保存和检索框架中的对象。
编程时,我一次又一次地质疑自己做对与否的方法。这是我正在做的一些例子。我在Swift 4中写作。
在使用以下代码获取对象时:
library(data.table)
dt <- data.table(x=c(1,2,3,NA,5),
y=c(1,1,NA,NA,NA),
z=c(NA,NA,NA,NA,NA),
d=c(2,2,2,2,2))
for (col in names(copy(dt))){
v = var(dt[[col]], na.rm = TRUE)
if (v == 0 | is.na(v)) dt[, (col) := NULL]
}
我想在方式中使用我的框架,闭包的结果可以直接在app中使用。所以我想在异步后台检索它们之后,我必须&#34;给它们回来&#34;在主队列中。我对这个建议是对的吗?我想知道,因为我在open func get(identifier: String, result:@escaping (NSObject?) -> ()) {
MKCacheStorageGlobals.dispatchQueue.async {
//Get object from memory
if let object = self.storageItems[identifier] {
DispatchQueue.main.async {
result(object)
}
return
}
//Else get object from disk
guard let storageHandler = self.storageHandler else {
DispatchQueue.main.async {
result(nil)
}
return
}
do {
if let object = try storageHandler.get(identifier: identifier) {
self.storageItems[identifier] = object
DispatchQueue.main.async {
result(object)
}
return
}
} catch {
print(error.localizedDescription)
}
DispatchQueue.main.async {
result(nil)
}
}
}
部分生成了许多DispatchQueue.main.(a)sync({ ... })
代码块。
我感谢各种提示,评论或更好的解决方案!
答案 0 :(得分:3)
有些无关紧要:通常这种异步代码不应该如此看待它调用结果处理程序的位置。调用者可能不希望结果在主队列上。通常,返回队列是“私有后台队列”(HealthKit),可在对象级别配置(URLSession),可在呼叫站点(大多数Dispatch)配置,或以任何方式(大部分基金会)未受到约束。 UIKit有时会承诺在主队列上调用完成处理程序,但这很不寻常。也就是说,如果你非常肯定每个调用者总是希望结果在主队列上,那很好,你可以保证。这种情况有时迫使人们将结果重新发送回其他队列,这是浪费。
除此之外,你如何清理它?几种方式。首先,这段代码是不必要的:
guard let storageHandler = self.storageHandler else {
DispatchQueue.main.async {
result(nil)
}
return
}
您可以使用optional-chaining在以后的用法中获得相同的结果:
if let object = try self.storageHandler?.get(identifier: identifier) {
“没有存储处理程序”和“存储处理程序中没有对象”之间的此功能没有区别,因此您可以使它们具有相同的代码路径。
但更强大的解决方法是提取这样的函数:
// Should only be called from MKCacheStorageGlobals.dispatchQueue
private func cacheValue(identifier: String) -> NSObject? {
do {
if let object = try self.storageHandler?.get(identifier: identifier) {
storageItems[identifier] = object
return object
}
} catch {
print(error.localizedDescription)
}
return nil
}
open func get(identifier: String,
result:@escaping (NSObject?) -> (),
queue: DispatchQueue = .main) {
MKCacheStorageGlobals.dispatchQueue.async {
let value = self.storageItems[identifier] ?? self.cacheValue(identifier: identifier)
queue.async {
result(value)
}
}
}
这将“获取和缓存值”问题与“调用结果处理程序”问题区分开来,因此您不必将两者混合使用。