Skip to content
This repository has been archived by the owner on Mar 16, 2020. It is now read-only.

No Unsubscribing from Signals #12

Closed
sotpt opened this issue Nov 13, 2015 · 11 comments
Closed

No Unsubscribing from Signals #12

sotpt opened this issue Nov 13, 2015 · 11 comments

Comments

@sotpt
Copy link

sotpt commented Nov 13, 2015

There is no mechanism to unsubscribe from signals.
Thus over the lifetime of the application callbacks to subscription blocks referencing deallocated objects will be sent. The amount of unnecessary callbacks will steadily increase while the application is used.
This will finally lead to performance issues, especially in the case when Signals are used to update UI elements in view controllers.

@JensRavens
Copy link
Owner

This is actually on purpose. Signals should be as immutable as possible. To get rid of a Signal just remove the reference to it, then it will deallocate and take all closures with it.

@JensRavens
Copy link
Owner

During the last days I was thinking about implementing something similar to reactive cocoa that gives back a subscription-object that can be used to explicitly unsubscribe from a signal. But that would also mean that subscribe is not chainable anymore. Would you think that tradeoff is ok?

@jaydillyo
Copy link

Why not use an inout parameter to return the subscription object? That would preserve chaining. Also, could maintain previous subscribe method that doesn't return a subscription object to maintain source compatibility.

@siuying
Copy link

siuying commented Dec 9, 2015

A use case: If I create a signal from NSNotificationCenter, I'd really want to unsubscribe it, where I can remove the observer from notification center.

@JensRavens
Copy link
Owner

This will be addressed in Interstellar 2, but currently you can achieve it with a workaround:

Create a custom object that subscribes itself to NSNotificationCenter. The only purpose of this object is to update a Signal<NSNotification> and keep a strong reference to it. Once you don't want to receive updates anymore, you can just let go of the signal (e.g setting it to nil on the object), so it will deallocate and release all subscriptions.

class NotificationObserver: NSObject {
    var signal: Signal<NSNotification>? = Signal<NSNotification>() {
        didSet {
            if signal == nil {
                NSNotificationCenter.defaultCenter().removeObserver(self)
            }
        }
    }

    override init() {
        super.init()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "update", name: NSUserDefaultsDidChangeNotification, object: nil)
    }

    func update(notification: NSNotification) {
        signal?.update(notification)
    }
}

let observer = NotificationObserver()
let signal = observer.signal //here is your signal
observer.signal = nil //unsubscribing

@siuying
Copy link

siuying commented Dec 9, 2015

@JensRavens thanks!

@robertjpayne
Copy link

I think it's pretty acceptable to make next and subscribe final methods that return a token to unsubscribe rather than keep chaining.

Chaining with both of these methods is a bit weird I think because to a viewer it would look as if the value stream was being modified but in reality it was just being 'tapped'.

Both RxSwift and ReactiveCocoa solve this via a separate API on vs subscribe*

@ashfurrow
Copy link
Contributor

@JensRavens I'm moving our project over to v2 as an experiment, and I just wanted to thank you for updating the readme along with the code 🙇 It's making things a lot easier.

@hypertalk
Copy link

It seems that mapping a Observable (or signal) will also add a subscription to the dictionary of the initial Observable. Since this does not return a ObservableToken there is no way to remove the subscription after it has been added from the map

@JensRavens
Copy link
Owner

@NeonOrion Yep, this is intentional. map is just convenience over subscribe. If you want all the options, use subscribe instead.

@JensRavens
Copy link
Owner

V2 has been released now, including the unsubscription api.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants