gpt4 book ai didi

swift - DispatchQueue 的正确实现方式

转载 作者:可可西里 更新时间:2023-11-01 00:56:00 24 4
gpt4 key购买 nike

我正在为一个应用程序项目编写一个简单的缓存框架,并在闭包中使用 GCD 和 DispatchQueues 来保存和检索框架中的对象。

在编程时,我一次又一次地质疑自己是否正确地完成了它。这是我正在做的一些例子。我正在用 Swift 4 编写。

在获取对象时,我使用了以下代码:

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)
}
}
}

我想以这种方式使用我的框架,闭包的结果可以直接在应用程序中使用。所以我想在后台异步检索它们之后,我必须在主队列中“归还它们”。我对这个建议正确吗?我想知道,因为我在 result() 部分生成了许多 DispatchQueue.main.(a)sync({ ... }) 代码块。

我感谢各种提示、评论或更好的解决方案!

最佳答案

有点无关紧要:通常这种异步代码不应该对它调用结果处理程序的位置如此自以为是。调用者可能不想要主队列中的结果。通常,返回队列是“私有(private)后台队列”(HealthKit),可在对象级别配置(URLSession),可在调用站点配置(大部分 Dispatch),或者以任何方式未 promise (大部分 Foundation)。 UIKit 事物有时会 promise 调用主队列上的完成处理程序,但这并不常见。也就是说,如果您非常确定每个调用此方法的人总是希望结果在主队列中,那很好,您可以保证。这种事情有时会迫使人们将结果重新发送回其他队列,这是一种浪费。

有了这个,你如何清理它?几种方式。首先,这段代码是不必要的:

   guard let storageHandler = self.storageHandler else {
DispatchQueue.main.async {
result(nil)
}
return
}

您可以只使用可选链接在以后的使用中获得相同的结果:

        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)
}
}
}

这将“获取和缓存值”问题与“调用结果处理程序”问题分开,因此您不必将两者混合。

关于swift - DispatchQueue 的正确实现方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48254603/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com