ReactiveCocoa v4.0 Release Notes

  • If you’re new to the Swift API and migrating from RAC 2, start with the 3.0 changes. This section only covers the differences between 3.0 and 4.0.

    Just like in RAC 3, because Objective-C is still in widespread use, 99% of RAC 2.x code will continue to work under RAC 4.0 without any changes. That is, RAC 2.x primitives are still available in RAC 4.0.

    ReactiveCocoa 4.0 targets Xcode 7.2.x and Swift 2.1.x, and it supports iOS 8.0, watchOS 2.0, tvOS 9.0 and OS X 10.9.

    🚦 Signal operators are protocol extensions

    The biggest change from RAC 3 to RAC 4 is that Signal and SignalProducer operators are implemented as protocol extensions instead of global functions. This is similar to many of the collection protocol changes in the Swift 2 standard library.

    🚦 This enables chaining signal operators with normal dot-method calling syntax, which makes autocompleting operators a lot easier. Previously the custom |> was required to enable chaining global functions without a mess of nested calls and parenthesis.

    /// RAC 3
    signal
      |> filter { $0 % 2 == 0 }
      |> map { $0 * $0 }
      |> observe { print($0) }
    
    /// RAC 4
    signal
      .filter { $0 % 2 == 0 }
      .map { $0 * $0 }
      .observeNext { print($0) }
    

    βž• Additionally, this means that SignalProducer operators are less β€œmagic”. In RAC 3 the Signal operators were implicitly lifted to work on SignalProducer via |>. This was a point of confusion for some, especially when browsing the 🚦 source looking for these operators. Now as protocol extensions, the SignalProducer operators are explicitly implemented in terms of their Signal counterpart when available.

    Removal of |> custom operator

    🚦 As already alluded to above, the custom |> operator for chaining signals has been removed. Instead standard method calling syntax is used for chaining operators.

    Event cases are no longer boxed

    🚚 The improvements to associated enum values in Swift 2 mean that Event case no longer need to be Boxed. In fact, the Box dependency has been removed completely from RAC 4.

    Replacements for the start and observer overloads

    🚚 The observe and start overloads taking next, error, etc. optional function parameters have been removed. They’ve been replaced with methods taking a single function with πŸ‘€ the target Event case β€” observeNext, startWithNext, and the same for failed and completed. See #2311 and #2318 for more details.

    πŸ“‡ Renamed try and catch operators

    The try and catch operators were renamed because of the addition of the error handling keywords with the same name. They are now attempt and flatMapError respectively. Also, tryMap was renamed to attemptMap for consistency.

    🚦 flatten and flatMap are now possible for all 4 combinations of Signal+SignalProducer

    🚦 This fills a gap that was missing in RAC 3. It’s a common pattern to have signals-of-signals or signals-of-producers. 🚦 The addition of flatten and flatMap over these makes it now possible to work with any combination of Signals and SignalProducers.

    πŸ“‡ Renamed Event.Error to Event.Failed

    🚦 The Error case of Event has changed to Failed. This aims to help clarify the terminating nature of failure/error events and puts them in the same tense as other terminating cases (Interrupted and Completed). Likewise, some operations and parameters have been renamed (e.g. Signal.observeError is now Signal.observeFailed, Observer.sendError is now Observer.sendFailed).

    🚦 Renamed signal generic parameters

    🚦 The generic parameters of Signal, SignalProducer, and other related types have been renamed to Value and Error from T and E respectively. This is in-line with changes to the standard library to give more descriptive names to type parameters for increased clarity. This should have limited impact, 🚦 only affecting generic, custom signal/producer extensions.

    βž• Added missing SignalProducer operators

    🚦 There were some Signal operators that were missing SignalProducer equivalents:

    • takeUntil
    • βœ… combineLatestWith
    • sampleOn
    • takeUntilReplacement
    • zipWith

    βž• Added new operators:

    • 🚦 Signal.on.
    • 🚦 Signal.merge(signals:).
    • 🚦 Signal.empty.
    • skipUntil.
    • replayLazily (#2639).

    πŸ“‡ Renamed PropertyOf<T> to AnyProperty<T>

    This is in-line with changes to the standard library in Swift 2.

    ✨ Enhancements to PropertyType

    MutableProperty received 3 new methods, similar to those in Atomic: modify, swap, and withValue. βž• Additionally, all PropertyTypes now have a signal: Signal<T> in addition to their existing producer: SignalProducer<T> property.

    Publicized Bag and Atomic

    Bag and Atomic are now public. These are useful when creating custom operators for RAC types.

    🚦 SignalProducer.buffer no longer has a default capacity

    🚦 In order to force users to think about the desired capacity, this no longer defaults to Int.max. Prior to this change one could have inadvertently cached every value emitted by the SignalProducer. This needs to be specified manually now.

    βž• Added SignalProducer.replayLazily for multicasting

    🚦 It’s still recommended to use SignalProducer.buffer or PropertyType when buffering behavior is desired. However, when you need to compose an existing SignalProducer to avoid duplicate side effects, this operator is now available.

    πŸ‘€ The full semantics of the operator are documented in the code, and you can see #2639 for full details.