swift3reactive-cocoareactive-cocoa-4reactive-swiftreactive-cocoa-5

RACSubject migration to ReactiveCocoa 5 (Swift 3)


I have to migrate an application from ReactiveCocoa 4 to ReactiveCocoa 5 (due to Swift 3 migration)

The old implementation uses some RACSubject instances for triggering (performOperationSubject.sendNext) an operation and for handling (didOperationSubject.subscribeNext) the result

internal class MyClass {

internal var performOperationSubject: RACSubject = RACSubject()
internal var didOperationSubject: RACSubject = RACSubject()

internal overide init() {
  super.init()
  self.performOperationSubject.subscribeNext { [weak self](_) in
    guard let strongSelf = self else { return }
    strongSelf.didOperationSubject.sendNext(result)

}

}

and when the MyClass instance is used

myClassInstance.didOperationSubject.subscribeNext { ... }

myClassInstance.performOperationSubject.sendNext(value)

Unfortunately the RACSubject is no more present in ReactiveCocoa 5 (ReactiveSwift)

How can I replace the RACSubject in this context?


Solution

  • You would use pipe which gives you an input observer and an output signal instead of using a RACSubject for both input and output. The example from the ReactiveSwift docs looks like this:

    let (signal, observer) = Signal<String, NoError>.pipe()
    
    signal
        .map { string in string.uppercased() }
        .observeValues { value in print(value) }
    
    observer.send(value: "a")     // Prints A
    observer.send(value: "b")     // Prints B
    observer.send(value: "c")     // Prints C
    

    Using Signal.pipe instead of RACSubject:

    Since the Signal type, like RACSubject, is always “hot”, there is a special class method for creating a controllable signal. The Signal.pipe method can replace the use of subjects, and expresses intent better by separating the observing API from the sending API.

    To use a pipe, set up observers on the signal as desired, then send values to the sink:

    let (signal, observer) = Signal<String, NoError>.pipe()
    
    signal.observeValue(value in
        // use value
    })
    
    observer.send(value: "the value")