在命令式Swift中,通常使用计算属性在不复制状态的情况下提供对数据的便捷访问。
假设我将此类用于命令式MVC:
class ImperativeUserManager {
private(set) var currentUser: User? {
didSet {
if oldValue != currentUser {
NotificationCenter.default.post(name: NSNotification.Name("userStateDidChange"), object: nil)
// Observers that receive this notification might then check either currentUser or userIsLoggedIn for the latest state
}
}
}
var userIsLoggedIn: Bool {
currentUser != nil
}
// ...
}
如果我想用Combine创建一个反应式等效项,例如,与SwiftUI一起使用,我可以轻松地添加@Published
到存储的属性中以生成Publisher
s,但不能添加到计算属性中。
@Published var userIsLoggedIn: Bool { // Error: Property wrapper cannot be applied to a computed property
currentUser != nil
}
我可以想到各种解决方法。我可以改为存储我的计算属性,并保持其更新。
选项1:使用属性观察器:
class ReactiveUserManager1: ObservableObject {
@Published private(set) var currentUser: User? {
didSet {
userIsLoggedIn = currentUser != nil
}
}
@Published private(set) var userIsLoggedIn: Bool = false
// ...
}
选项2:Subscriber
在我自己的班级中使用:
class ReactiveUserManager2: ObservableObject {
@Published private(set) var currentUser: User?
@Published private(set) var userIsLoggedIn: Bool = false
private var subscribers = Set<AnyCancellable>()
init() {
$currentUser
.map { $0 != nil }
.assign(to: \.userIsLoggedIn, on: self)
.store(in: &subscribers)
}
// ...
}
但是,这些解决方法不如计算属性好。它们复制状态,并且不会同时更新两个属性。
与将Publisher
Combine 添加到Combine中的计算属性相比,什么是适当的等效方法?
根据观察到的变量
—
user28434
计算属性是属于派生属性的一种属性。它们的值取决于依赖项的值。仅出于这个原因,可以说它们绝不会像那样表现
—
nayem
ObservableObject
。本质上,您假设一个ObservableObject
对象应该具有变异能力,根据定义,该属性不是Computed Property的情况。
您找到解决方案了吗?我处于完全相同的情况下,我想避免出现状态,但仍然可以发布
—
erotsppa