skip to Main Content

I have my networking library based on Combine. Anywhere in my app I can make a request and the networking library returns a publisher, it doesn’t have access to the AnyCancellable that is created that actually triggers the pipeline. What I need is the ability to cancel all network requests when the use logs out. Is there a way to cancel Combine pipelines from the publisher not the AnyCancellable.

Here is an example:

    var subscribers = [AnyCancellable]()
    let url = URL(string:"https://www.apeth.com/pep/manny.jpg")!
    let request: AnyPublisher<UIImage, URLError> = URLSession.shared.dataTaskPublisher(for: url)
        .compactMap { UIImage(data:$0.data) }
        .share()
        .eraseToAnyPublisher()
    
    request
        .sink(receiveCompletion: { _ in
            print("subscription2 completed")
        }, receiveValue: { image in
            print("subscription1 value: (image.scale)")
        })
        .store(in: &subscribers)
    
    // request.cancel()

I would like to call something like request.cancel() on the publisher so that the receiveValue is never triggered.

2

Answers


  1. The sink method returns a single AnyCancellable that you can store in
    a dedicated property for the request instead of storing the cancellable in the array.

    When you need to cancel the subscription, just deinitialize the cancellable, because, according to the documentation "An AnyCancellable instance automatically calls cancel() when deinitialized."

    private var requestCancellable: AnyCancellable?
    
    func setUpSubscription() {
        requestCancellable = request
            .sink(receiveCompletion: { _ in
                print("subscription2 completed")
            }, receiveValue: { image in
                print("subscription1 value: (image.scale)")
            })
    }
    
    func cancelSubscription() {
        requestCancellable = nil
    }
    
    Login or Signup to reply.
  2. What I need is the ability to cancel all network requests when the use logs out.

    I suggest you setup a publisher that emits when the user logs out. Then in your API system, you can use prefix(untilOutputFrom: logoutPublisher).

    That way, all your network requests will cancel when the logoutPublisher emits.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search