Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent sink receiveValue closure from being called immediately

Consider the following code (you can c&p it directly into a playground):

class Foo: ObservableObject {
    @Published var bar = "bar"
}

let foo = Foo()
let someSubscriber = foo.$bar
    .sink { value in
        print("value is \(value)")
    }

Although Foo has just been initialised once and it's member bar never changed, the sink executes it's receiveValue closure immediately. Is there any way to prevent this initial call from happening, e.g. is there an operator I might have overlooked?

like image 549
ff10 Avatar asked Jan 01 '23 06:01

ff10


1 Answers

You can use the dropFirst operator. With no argument, it drops just the first output from upstream.

let someSubscriber = foo.$bar
    .dropFirst()
    .sink { value in
        print("value is \(value)")
    }

To address issues raised in the comments:

Each implementation of Publisher can decide what to do with each new subscriber. It is a policy decision, not generally a design deficiency. Different Publishers make different decisions. Here are some examples:

  • PassthroughSubject doesn't immediately publish anything.
  • CurrentValueSubject immediately publishes its current value.
  • NSObject.KeyValueObservingPublisher immediately publishes the current value of the observed property if and only if it is created with the .initial option.
  • Published.Publisher (which is the type you get for an @Published property) publishes the current value of the property immediately.
like image 143
rob mayoff Avatar answered Jan 02 '23 21:01

rob mayoff