Im zwingenden Swift ist es üblich, berechnete Eigenschaften zu verwenden, um einen bequemen Zugriff auf Daten zu ermöglichen, ohne den Status zu duplizieren.
Angenommen, ich habe diese Klasse für die zwingende Verwendung von MVC erstellt:
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
}
// ...
}
Wenn ich mit Combine ein reaktives Äquivalent erstellen möchte, z. B. zur Verwendung mit SwiftUI, kann ich @Published
gespeicherte Eigenschaften problemlos hinzufügen , um Publisher
s zu generieren , jedoch nicht für berechnete Eigenschaften.
@Published var userIsLoggedIn: Bool { // Error: Property wrapper cannot be applied to a computed property
currentUser != nil
}
Es gibt verschiedene Problemumgehungen, an die ich denken könnte. Ich könnte stattdessen meine berechnete Eigenschaft speichern und auf dem neuesten Stand halten.
Option 1: Verwenden eines Eigenschaftsbeobachters:
class ReactiveUserManager1: ObservableObject {
@Published private(set) var currentUser: User? {
didSet {
userIsLoggedIn = currentUser != nil
}
}
@Published private(set) var userIsLoggedIn: Bool = false
// ...
}
Option 2: Verwenden von a Subscriber
in meiner eigenen Klasse:
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)
}
// ...
}
Diese Problemumgehungen sind jedoch nicht so elegant wie berechnete Eigenschaften. Sie duplizieren den Status und aktualisieren nicht beide Eigenschaften gleichzeitig.
Was wäre ein angemessenes Äquivalent zum Hinzufügen von a Publisher
zu einer berechneten Eigenschaft in Combine?
ObservableObject
. Sie gehen von Natur aus davon aus, dass ein ObservableObject
Objekt mutieren kann, was per Definition für die berechnete Eigenschaft nicht der Fall ist .