Я относительно новичок в концепциях реактивного программирования, и я пытаюсь создать простую модель представления для обновления @Published Bool
значений, которые используются для обновления пользовательского интерфейса с помощью SwiftUI.
Эта конкретная модель установка этих значений Bool
на основе других значений из структуры WatchConnectivity
при их изменении с течением времени.
Несмотря на то, что это простой пример, и он работает, я чувствую, что упускаю возможности уменьшить избыточность.
В частности, странно, что я повторяю логи c, используемые для установки начальных значений appNotInstalled
и complicationNotInstalled
позже, когда я использую Publishers.CombineLatest
и Publishers.CombineLatest3
.
Несмотря на то, что начальные значения передаются через издателей, поэтому они go через конвейеры CombineLatest
и устанавливают начальные значения, кажется неправильным произвольно устанавливать опубликованные переменные на true
или false
, но компилятор заставляет меня устанавливать для них начальные значения где-то.
Если я не устанавливаю начальные значения, я получаю ошибку Variable 'self.appNotInstalled' used before being initialized
.
Есть ли ва? y Я могу избежать установки начальных значений, не делая их равными nil, или другим способом избежать дублирования логики c, используемой для определения их значений?
Вот рабочий код, который у меня есть:
class WatchConnectivityModel: ObservableObject {
// values used to show/hide UI
@Published var appNotInstalled: Bool
@Published var complicationNotInstalled: Bool
private var cancellables: [AnyCancellable] = []
init() {
// initialize based on the values of everything at class init
let activated = WCSession.default.activationState == .activated
let appInstalled = WCSession.default.isWatchAppInstalled
let complicationInstalled = WCSession.default.isComplicationEnabled
appNotInstalled = !(activated && appInstalled)
complicationNotInstalled = activated && appInstalled && !complicationInstalled
// set up the publishers for any changes
let activationStatePublisher = WCSession.default.publisher(for: \.activationState)
let isWatchAppInstalledPublisher = WCSession.default
.publisher(for: \.isWatchAppInstalled)
let isComplicationEnabledPublisher = WCSession.default
.publisher(for: \.isComplicationEnabled)
// set up assignment of appNotInstalled for changes
Publishers.CombineLatest(activationStatePublisher.removeDuplicates(),
isWatchAppInstalledPublisher.removeDuplicates())
.map { (state, installed) in
// repeated logic from above
return !(state == .activated && installed)
}.receive(on: RunLoop.main)
.assign(to: \.appNotInstalled, on: self)
.store(in: &cancellables)
// set up assignment of complicationNotInstalled for changes
Publishers.CombineLatest3(activationStatePublisher.removeDuplicates(),
isWatchAppInstalledPublisher.removeDuplicates(),
isComplicationEnabledPublisher.removeDuplicates())
.map { (state, appInstalled, complicationInstalled) in
// repeated logic again
return state == .activated && appInstalled && !complicationInstalled
}.receive(on: RunLoop.main)
.assign(to: \.complicationNotInstalled, on: self)
.store(in: &cancellables)
}
}