Search code examples
iosswiftcombine

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

  • 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)
        }
    }