在 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 值可以忽略。