Home > Software engineering >  Combine: resetting observed boolean within sink() call?
Combine: resetting observed boolean within sink() call?

Time:04-12

I have the following code:

    $myBoolean
        .debounce(for: 2, scheduler: RunLoop.main)
        .removeDuplicates()
        .sink { newValue in
            self.myBoolean = false
            ....... 
            ...... (closure called every 2 seconds if I don't use `removeDuplicates()`)
        }
        .store(in: &subscribers)

I am using sink() on a @Published var in my observable object. Different parts of the app can set that boolean to true. When that happens, I want the code in sink() to run.

When that happens I want the code to reset myBoolean to false. So, only when I know the sink() code runs I want the boolean to be set back to false.

How can I set myBoolean back to false only when the sink() code runs without cause endless calls to the sink()?

myBoolean is declared like so:

@Published fileprivate var myBoolean:Bool = false

CodePudding user response:

Using Custom type MyBool and filter operator you can get similar behaviour.


import Combine

class Abc: ObservableObject {
    struct MyBool: Equatable {
        let value: Bool
        let isFromSinkCall: Bool
    }
    
    @Published var myBoolean: MyBool = .init(value: true, isFromSinkCall: false)
    
    private var subscribers = Set<AnyCancellable>()
    
    init() {
        setup()
    }
    
    func setup() {
        $myBoolean
            .debounce(for: 2, scheduler: RunLoop.main)
            .removeDuplicates()
            .filter({ !$0.isFromSinkCall })
            .sink { newValue in
                self.myBoolean = .init(value: false, isFromSinkCall: true)
            }
            .store(in: &subscribers)
    }
}

  • Related