Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get current value from ReactiveCocoa signal?

I have signal returning NSNumber:

RACSignal *signal = ....

Then in some place of code I want to get value of signal in the moment of execution, something like:

NSNumber *value = [code that extracts current value of signal];
like image 210
Leszek Zarna Avatar asked Jun 19 '13 20:06

Leszek Zarna


3 Answers

Signals have no notion of a "current" value. Values are sent, then they disappear — they're very ephemeral (unless a replay subject or other tricks are used).

You probably want to subscribe to that signal. Check out the Framework Overview and the examples in the README for a deeper explanation.

like image 181
Justin Spahr-Summers Avatar answered Nov 14 '22 11:11

Justin Spahr-Summers


  1. Your "current value from ReactiveCocoa signal" in language of Reactive - is a subscription to this signal.

The -subscribe... methods give you access to the current and future values in a signal:

    [signal subscribeNext:^(id x) {
        NSLog(@"Current value = %@", x);
    }];
  1. Another way: if you would like to use this value with another values - use combineLatest:reduce: method like this:

    RACSignal *calculationWithCurrentValueSignal =
      [RACSignal combineLatest:@[signalWithCurrentValueThatNeeded, anotherSignal]
                        reduce:^id(NSNumber *myCurrentValue, NSNumber *valueFromAnotherSignal) {
                           //do your calculations with this values..
                          return newValue;
                        }];
    
like image 2
skywinder Avatar answered Nov 14 '22 11:11

skywinder


are the answers valid for the Swift version as well?

Image an SignalPipe observing a changes on an object property. When subscribing to the signal from several other objects, i.e. queue.queueCountSignal.observeNext({...}), the observe block will be executed the next time the property changes. Is there a way to ask for the current value or trigger the observeNextBlock?

I do not want to use a SignalProducer (that can be started explicitly) because this would mean that I need to collect the observeNext blocks from every object the signal is needed. I also do not want to create several signal producer for the same thing – or is this actually wanted?

Here is the example code to make more clear

import ReactiveCocoa

class SwipingQueueWithSignals<T> : SwipingQueue<T> {

    override var count: Int {
        didSet(oldQueueCount) {
            let newQueueCount = self.count
            queueCountSignalObserver.sendNext(newQueueCount)
    }

    let queueCountSignal: Signal<Int, NoError>
    private let queueCountSignalObserver: Observer<Int, NoError>

    init() {
        (self.queueCountSignal, self.queueCountSignalObserver) = Signal<Int, NoError>.pipe()
        super.init()
    }
}

// Something like this 
queue.queueCountSignal.
    .observeNext { next in print(next) }
    .lookupCurrentValueNow()
like image 1
Gerardo Navarro Suarez Avatar answered Nov 14 '22 09:11

Gerardo Navarro Suarez