Upgrade to ReactiveCocoa v.4

Original author: Jordan Schaenzle
  • Transfer
image

If you have ever been interested in the ReactiveCocoa framework , you have noticed that there are a small number of posts on the topic of reactive programming and the ReactiveCocoa framework, such as Meet the ReactiveCocoa , or The Best World with ReactiveCocoa . Until today, all of these posts have been about ReactiveCocoa 2 versions, which was written in and for Objective-C. Now the Swift language is gaining popularity, the developers of ReactiveCocoa are working hard on a new version, which will be written in Swift and will have some functional features that are fundamental for this language.

I suspect that many of you, like me, desperately left Objective-C and switched to Swift. If you would like to use ReactiveCocoa with a new language, I highly recommend that you try using the new version of ReactiveCocoa. And I am sure that our community will greatly benefit from the contribution you have made. On the other hand, if you are working on large business applications in production for a specific customer, I must tell you - do not do this or think carefully before using it. But we will talk about this further, if anyone is interested - I ask for a cat.

ReactiveCocoa status to date


At the time of this writing, ReactiveCocoa (from now on referred to as RAC) is in an undefined state. When the first version of Swift was published, developers began work on a third version of RAC. However, not so long ago, Apple released Xcode 7.0, which contains support for Swift version 2.0. This is caused by some critical changes in RAC3, but there are also some significant simplifications with respect to the new API. The changes pushed developers to start work on RAC4.

RAC4 is still far from being able to use it to create stable applications, but many are already doing this, and care must be taken because the system changes frequently. The protocol of changes reads: “Critical changes are possible, so be prepared for this before integrating it into the application.” But still, if you’re really ready to try out RAC4, I’ll share some tips to help you get started using the new version of RAC.

Say goodbye to RACSignal


In RAC2, all signals used the RACSignal type. The signal can be of two types - hot (hot) and cold (cold). A hot signal has at least one subscriber that processes events sent to it, it reminds me of a closed circuit that has no beginning and no end. A cold signal is one of the signals that may not have subscribers and therefore does not provide any action or transmission of information. It can be divided into stages, a cold signal does not start its work until someone subscribes to it.

RAC4 divides the concept of signals into two different types: Signal Producers and Signals. The signal procedure is very similar to RACSignal; the signal is inactive until it is triggered. The developers changed the terminology of the word subscribed to started, since this option describes this signal state more accurately. For example, a SignalProducer may have multiple subscribers who are subscribed to receive events, but the signal does not become active, and subscribers will not see any events until it is triggered for some reason. The signal is triggered by calling the start () method.

Another new type is Signal. Signal is like a fire hose. You connect it to the source and events flow through it. As long as there is no trigger, you can use it to work like SignalProducer. Signals also do not support any history. When a subscriber subscribes to events from a signal, he will receive all future events, but not a single past event. Signals are very useful for transmitting information in real time, which occurs as a result of user interaction with the application. For example, a signal can send numbers and symbols that a user enters in a text field.

Defer method removed


You will also notice that RAC4 no longer contains a defer operation. Unlike calling a function in RAC2, we will often use transfer blocks if we need to write a function that returns a signal and also performs some other operations (like registering debugged text) when the signal goes into a hot state.

Defer options in RAC4 no longer exist. To demonstrate this example, the authors suggest that we consider started, similar to the following.

In Swift language:
func logIn(username: String, password: String) -> SignalProducer {
    return accountManager.logIn(username, password: password)
        .on( started: {
            print("Logging in...")
        }
}

unlike Objective-C
- (RACSignal *)logInWithUsername:(NSString *)username andPassword:(NSString *)password {
    return [RACSignal defer:^{
        NSLog("Logging in...");
        return [accountManager logInUser:username withPassword:password];
    }];
}

MutableProperties


One of the features that I really like about RAC4 is the MutableProperty class. MutableProperty is a container for an object that changes at runtime. It also contains a signal initiator that automatically sends each value that has been assigned to the subscriber.

Strong typing


The most difficult thing for me when switching to RAC4 was getting used to strict typing related to signals. In RAC2, signals have no information about objects or errors. The restriction was only that all objects sent to them should be obtained from NS objects (not primitives). In RAC4, a signal is defined by this type for the values ​​defined for it and for errors that may occur. For instance,
var signalA = SignalProducer ...

defines a signal that can be sent only to objects of type String, and only ReallyBadError can occur in this case. Type safety has some advantages in that it becomes more clear what information was sent, but at the same time it complicates the combination of signals.

In RAC2, you can easily take the signal that Bananas send, connect it to the signal that Oranges send, and associate the result with the signals that the Pineapples send. The resulting signal will not have the proper form, but the code will be compiled.

In RAC4, the compiler will show errors if you try to return signals sending Apples from a function that possibly returns the signal that Peaches sends.

Signal Combination


Signal combining is more complicated due to the fact that the authors got rid of the good functions that used signal arrays to form bindings, merges, etc. ... For example, in Objective-C, if you want to combine two signals, you must do the following :
-(RACSignal *) bakeCakeWith:(NSArray *)ingredients {
    RACSignal *preheatSignal = [self.oven preheat:@(350)];
    RACSignal *bakeSignal = [self.baker combine:ingredients];
    return [RACSignal concat:@[preheatSignal, bakeSignal];
}

Now in RAC4, you should do the following.
func bakeCake(ingredients: Array) -> SignalProducer {
    let (combinerSignal, combinerSink) = SignalProducer.buffer(1)
    sendNext(combinerSink, self.oven.preheat(350))
    sendNext(combinerSink, self.baker.combine(ingredients))
    return combinerSignal.flatten(.Concat)
}

But you can create your own function that will easily perform the same as in Objective-C.

I definitely had some frustration with the Swift and RAC4 languages, but it was a really fun way to go. I plan to keep moving forward, and I urge you to do the same.

Here are some really good sources to learn more about RAC:
Stanfy MadCode Meetup # 11: Why do you need to switch from Obj-C to Swift, or let's talk about ReactiveCocoa v4
An Introduction to ReactiveCocoa
MVVM WITH REACTIVECOCOA 3.0
Reactive Swift: upgrading to ReactiveCocoa 3.0

Also popular now: