Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is sink never called in my combine pipeline? [duplicate]

Here is my pipeline:

URLSession.shared
      .dataTaskPublisher(for: urlRequest)
      .map { $0.data }
      .mapError { ...... }
      .eraseToAnyPublisher()
      .decode(type: MyObject.self, decoder: JSONDecoder())
      .receive(on: RunLoop.main)
      .catch { [weak self] error -> Just<MyObject> in
        guard let self = self else { return Just(emptyPayload) }
        self.hasError = true
        return Just(emptyPayload)
    }
    .sink(
      receiveCompletion: { [weak self] _ in
        print("i'm here")
      },
      receiveValue: { [weak self] value in
        print("value")
      }
    )

Why is sink never called?

like image 957
user1366265 Avatar asked Dec 11 '19 19:12

user1366265


1 Answers

dataTaskPublisher(for: urlRequest) will send values asynchronously. When program execution leaves your current scope, there are no more references to your pipeline and ARC destroys your pipeline before the network request has completed.

Your pipeline returns a Cancellable. Either assign that Cancellable directly to an instance variable or add the store(in:) operator to your pipeline.

Also worth mentioning is that if you mess around with Combine pipelines in an Xcode playground, your pipelines may live longer than you'd expect because the Playground tries to be smart about holding on to references for the sake of making experimentation easier. See this answer for an async example you can run in a playground, even though it applies neither of the fixes I mentioned.

like image 127
Gil Birman Avatar answered Nov 03 '22 19:11

Gil Birman