'How do I observe changes on an array with Combine framework?

How can I observe changes on an array with Combine framework but without SwiftUI?

Basically, I want this sink block to get called when an element is added or removed.

import Combine

var list = ["A", "B", "C"]
list.publisher
    .collect()
    .sink { value in
        print(value)
    }

// I want to observe these changes.
list.append("D")
list.removeAll { $0 == "B"}

I read this article and I know @Published property wrapper works this way. But I can't use SwiftUI and am looking for another solution.



Solution 1:[1]

Combine is a completely separate framework from SwiftUI, so it can be used on its own.

I would add a publisher for the list by using the @Published attribute. You can then receive events off of that.

You'll need to have the resulting AnyCancellable stored (such as in a set) so that the subscription can be torn down properly and doesn't deallocate immediately.

class MyClass {
    @Published var list: [String] = []
    
    private var cancellables: Set<AnyCancellable> = []
    
    func setUp() {
        $list
            .receive(on: RunLoop.main)
            .sink { listItems in
                // Items changed
            }.store(in: &cancellables)
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1