在 Combine 中创建多个 Publisher 哪个更好? AnyCancellable for each 或 Set<AnyCancellable> with .store(in: &self.cancellableSet)?
Which is better when creating multiple Publishers in Combine? AnyCancellable for each or Set<AnyCancellable> with .store(in: &self.cancellableSet)?
总的来说,我对 Combine 和响应式编程有些陌生。我想我遇到过两种不同的方法来做同样的事情,但我想知道为什么我应该选择一种而不是另一种。
我有一个简单的模型,用于存储和发布与 Apple Watch 状态相关的值。以下是我认为我在做同样事情的两种不同方式。
在第一种方法中,我为每个 Publisher
:
使用单独的 AnyCancellable?
class WatchConnectivityModel: ObservableObject {
init() {
activationState = WCSession.default.activationState
isWatchAppInstalled = WCSession.default.isWatchAppInstalled
isComplicationEnabled = WCSession.default.isComplicationEnabled
assignPublishers()
}
@Published var activationState: WCSessionActivationState
@Published var isWatchAppInstalled: Bool
@Published var isComplicationEnabled: Bool
private var activationStateStream: AnyCancellable?
private var isWatchAppInstalledStream: AnyCancellable?
private var isComplicationEnabledStream: AnyCancellable?
private func assignPublishers() {
activationStateStream = WCSession.default
.publisher(for: \.activationState)
.receive(on: RunLoop.main)
.assign(to: \.activationState, on: self)
isWatchAppInstalledStream = WCSession.default
.publisher(for: \.isWatchAppInstalled)
.receive(on: RunLoop.main)
.assign(to: \.isWatchAppInstalled, on: self)
isComplicationEnabledStream = WCSession.default
.publisher(for: \.isComplicationEnabled)
.receive(on: RunLoop.main)
.assign(to: \.isComplicationEnabled, on: self)
}
}
这是我的第二种方法,但我没有使用单独的 AnyCancellable?
对象,而是在每个 Publisher
:[=21 上使用单个 Set<AnyCancellable>
和 .store(in: &self.cancellableSet)
=]
class WatchConnectivityModel: ObservableObject {
init() {
activationState = WCSession.default.activationState
isWatchAppInstalled = WCSession.default.isWatchAppInstalled
isComplicationEnabled = WCSession.default.isComplicationEnabled
assignPublishers()
}
@Published var activationState: WCSessionActivationState
@Published var isWatchAppInstalled: Bool
@Published var isComplicationEnabled: Bool
private var cancellableSet: Set<AnyCancellable> = []
private func assignPublishers() {
_ = WCSession.default
.publisher(for: \.activationState)
.receive(on: RunLoop.main)
.assign(to: \.activationState, on: self)
.store(in: &self.cancellableSet)
_ = WCSession.default
.publisher(for: \.isWatchAppInstalled)
.receive(on: RunLoop.main)
.assign(to: \.isWatchAppInstalled, on: self)
.store(in: &self.cancellableSet)
_ = WCSession.default
.publisher(for: \.isComplicationEnabled)
.receive(on: RunLoop.main)
.assign(to: \.isComplicationEnabled, on: self)
.store(in: &self.cancellableSet)
}
}
我猜想如果我需要手动对三个特定流中的一个执行某些操作,第一种方法会更好,但在这种情况下我不需要这样做。除此之外,还有什么可以使这些方法中的一种比另一种更好?在内存管理方面,有什么我遗漏的重要内容吗?
第二个对我来说似乎有点奇怪,因为整个 _ =
部分,因为它看起来像是一个难以解释的额外工件:为什么我要将这整个东西分配给任何东西?第一个选项避免了可能的混淆。
没有特别的理由为每个订阅创建一个单独的变量,如果所有订阅将同时被销毁。
另请注意,您不需要使用 Set<AnyCancellable>
。数组同样有效或更好:
private var tickets: [AnyCancellable] = []
您根本不需要“整个 _ =
部分”。 store(in:)
方法 returns Void
,因此编译器知道 return 值可以忽略。
总的来说,我对 Combine 和响应式编程有些陌生。我想我遇到过两种不同的方法来做同样的事情,但我想知道为什么我应该选择一种而不是另一种。
我有一个简单的模型,用于存储和发布与 Apple Watch 状态相关的值。以下是我认为我在做同样事情的两种不同方式。
在第一种方法中,我为每个 Publisher
:
AnyCancellable?
class WatchConnectivityModel: ObservableObject {
init() {
activationState = WCSession.default.activationState
isWatchAppInstalled = WCSession.default.isWatchAppInstalled
isComplicationEnabled = WCSession.default.isComplicationEnabled
assignPublishers()
}
@Published var activationState: WCSessionActivationState
@Published var isWatchAppInstalled: Bool
@Published var isComplicationEnabled: Bool
private var activationStateStream: AnyCancellable?
private var isWatchAppInstalledStream: AnyCancellable?
private var isComplicationEnabledStream: AnyCancellable?
private func assignPublishers() {
activationStateStream = WCSession.default
.publisher(for: \.activationState)
.receive(on: RunLoop.main)
.assign(to: \.activationState, on: self)
isWatchAppInstalledStream = WCSession.default
.publisher(for: \.isWatchAppInstalled)
.receive(on: RunLoop.main)
.assign(to: \.isWatchAppInstalled, on: self)
isComplicationEnabledStream = WCSession.default
.publisher(for: \.isComplicationEnabled)
.receive(on: RunLoop.main)
.assign(to: \.isComplicationEnabled, on: self)
}
}
这是我的第二种方法,但我没有使用单独的 AnyCancellable?
对象,而是在每个 Publisher
:[=21 上使用单个 Set<AnyCancellable>
和 .store(in: &self.cancellableSet)
=]
class WatchConnectivityModel: ObservableObject {
init() {
activationState = WCSession.default.activationState
isWatchAppInstalled = WCSession.default.isWatchAppInstalled
isComplicationEnabled = WCSession.default.isComplicationEnabled
assignPublishers()
}
@Published var activationState: WCSessionActivationState
@Published var isWatchAppInstalled: Bool
@Published var isComplicationEnabled: Bool
private var cancellableSet: Set<AnyCancellable> = []
private func assignPublishers() {
_ = WCSession.default
.publisher(for: \.activationState)
.receive(on: RunLoop.main)
.assign(to: \.activationState, on: self)
.store(in: &self.cancellableSet)
_ = WCSession.default
.publisher(for: \.isWatchAppInstalled)
.receive(on: RunLoop.main)
.assign(to: \.isWatchAppInstalled, on: self)
.store(in: &self.cancellableSet)
_ = WCSession.default
.publisher(for: \.isComplicationEnabled)
.receive(on: RunLoop.main)
.assign(to: \.isComplicationEnabled, on: self)
.store(in: &self.cancellableSet)
}
}
我猜想如果我需要手动对三个特定流中的一个执行某些操作,第一种方法会更好,但在这种情况下我不需要这样做。除此之外,还有什么可以使这些方法中的一种比另一种更好?在内存管理方面,有什么我遗漏的重要内容吗?
第二个对我来说似乎有点奇怪,因为整个 _ =
部分,因为它看起来像是一个难以解释的额外工件:为什么我要将这整个东西分配给任何东西?第一个选项避免了可能的混淆。
没有特别的理由为每个订阅创建一个单独的变量,如果所有订阅将同时被销毁。
另请注意,您不需要使用 Set<AnyCancellable>
。数组同样有效或更好:
private var tickets: [AnyCancellable] = []
您根本不需要“整个 _ =
部分”。 store(in:)
方法 returns Void
,因此编译器知道 return 值可以忽略。