Home > Software design >  How to map a completed event to an interrupt event when take(duringLifetimeOf:) happened in Reactive
How to map a completed event to an interrupt event when take(duringLifetimeOf:) happened in Reactive

Time:03-02

For example, I want to send a request in my viewModel, if the viewModel is dealloc. The request signal should send interrupt event.

This is my code

func request() -> SignalProducer<Data, Error> {
    let request: SignalProducer<Data, Error> = ..... (This signal is from another module)
    return request.take(duringLifetimeOf: self)
}

This code will send a completed event instead of an interrupt event when self is dealloc. Because take(duringLifetimeOf:) API said:

Forward events from self until object deinitializes, at which point the returned producer will complete.

If I am the caller of this request(). I want to know whether my request is done. If the request is canceled due to the "self" being dealloc . Then I will get a completed event. This is not reasonable.

Is my thought right about mapping the completed event to the interrupt event?

What to do if my thought is right?

CodePudding user response:

I've found that caring about the distinction between completed and interrupted events is often an anti-pattern, and there may be a better way to do what you are trying to do if you can share how exactly you're consuming the request() function.

That said, here's a little custom operator that I think will do what you are trying to do:

extension SignalProducer {
    func interrupt(after lifetime: Lifetime) -> SignalProducer<Value, Error> {
        return SignalProducer<Value, Error> { observer, innerLifetime in
            innerLifetime  = self.start(observer)
            innerLifetime  = lifetime.observeEnded(observer.sendInterrupted)
        }
    }
}

Then you can do this instead of using take(duringLifetimeOf:):

func request() -> SignalProducer<Data, Error> {
    let request: SignalProducer<Data, Error> = ..... (This signal is from another module)
    return request.interrupt(after: self.reactive.lifetime)
}
  • Related