0

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.

4
  • Look up AnyCancellable and AnyPublisher. BTW @Published works with SwiftUI but it is a Combine wrapper. Commented May 13, 2022 at 19:44
  • Does that mean I need to implement my own publisher for this? Commented May 13, 2022 at 20:01
  • You need to store instance of AnyCancellable. Subscriptions return an instance of AnyCancellable as a “cancellation token,” .In above example your subscription will be cancelled automatically after collecting all values, and ignoring other commands like append. Check stackoverflow.com/questions/63543450/… Commented May 13, 2022 at 20:49
  • @TusharSharma Thank you for your comment! But I'm not sure if I understand you correctly. I think the issue is the publisher is completed before I start mutating the list. Created a gist as formatting doesn't seem to work in comment... gist.github.com/taichino/479ae77c15bd68ca6fbd871fe4badb30 Commented May 13, 2022 at 21:24

1 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.