我目前正在开发一个系统,在更改时将一些
UserDefaults
值传递给另一个系统。我试图使用 UserDefaults.standard.publisher
(如下例所示)来观察特定值的变化,但甚至没有收到更新。然后我开始尝试 UserDefaults 多线程,看看它是否真的像 Apple 文档声称的那样是线程安全的。我在下面构建了以下示例,但似乎无法找到该行为的解释。我现在的问题是如何使发布者始终收到更新的值并且线程安全?
示例代码import Combine
import Foundation
let key = "value"
private extension UserDefaults {
@objc dynamic var value: Int {
get { integer(forKey: key) }
set { set(newValue, forKey: key) }
}
}
print("Starting")
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
dispatchGroup.enter()
DispatchQueue.global().async {
UserDefaults.standard.value = 0
let publisher = UserDefaults.standard.publisher(for: \.value, options: .new)
let cancellable = publisher.sink { value in
print("Received: \(value)")
}
UserDefaults.standard.value = 1
UserDefaults.standard.setValue(2, forKey: key)
DispatchQueue.global().async {
UserDefaults.standard.setValue(3, forKey: key)
dispatchGroup.leave()
}
dispatchGroup.leave()
}
dispatchGroup.wait()
print("Finished")
输出Starting
Received: 1
Received: 1
Received: 2
Finished
我在下面构建了以下示例,但似乎找不到该行为的解释。当第一个异步块退出时,可取消项超出范围,订阅结束。然后,执行第二个异步块,将值设置为 3 并释放调度组。
如果您在顶层声明可取消,您可以看到这一点:
var cancellable: AnyCancellable?
并分配给它:
DispatchQueue.global().async {
cancellable = publisher.sink { value in
print("Combine Received: \(value)")
}
// ...