ReactiveSwift Documentation

repository·master·Indexed 25 days ago

https://github.com/reactivecocoa/reactiveswift

A framework for managing streams of values over time using composable, declarative, and flexible primitives. It provides core types such as Signal, SignalProducer, and Property, and defines a strict event grammar (value, failed, completed, interrupted) to represent common programming patterns like delegates, callbacks, and notifications.

Tokens
10.3K
Snippets
21
Records
52
Agent score
80%

What's inside ReactiveSwift

  1. Use SignalProducers for deferred or repeatable work

    master

    SignalProducer represents a task or operation (like a network request) that can be started multiple times.

    Key Characteristics:

    • Lazy: No work is performed until you call start().
    • Repeatable: Each call to start() creates a new underlying operation/signal. Different observers may see different event sequences.
    • Cancellable: Starting a producer returns a Disposable used to interrupt the work.

    Manipulation:

    • Use startWithSignal() to get access to the produced signal.
    • Use lift to apply signal primitives (like map or filter) to a SignalProducer.
  2. Perform side-effecting work with Action

    master

    An action (Action) is used to perform work when executed with an input. It is ideal for user interactions like button clicks.

    Features:

    • Generates zero or more output values or failures during execution.
    • Can be automatically disabled based on a Property, which can be used to drive UI state (e.g., disabling a button while a request is in progress).
  3. Control execution with Schedulers

    master

    A scheduler (Scheduler) is a serial execution queue used to perform work or deliver results.

    Key Properties:

    • Serial: Schedulers always execute tasks serially.
    • Cancellable: Unlike standard GCD queues, schedulers support cancellation via Disposable.
    • Non-blocking: Most schedulers (except ImmediateScheduler) do not offer synchronous execution to prevent deadlocks.

    Use schedulers to order when signals deliver events or when signal producers start their work.

  4. Understand ReactiveSwift Events

    master

    An event (Event) is the fundamental unit of communication in ReactiveSwift. It represents something that has happened (e.g., a button press, API data, or an error).

    An Event is an enumeration that can be one of the following:

    • value: Provides a new piece of data from the source.
    • failed: Indicates an error occurred. These are parameterized by an ErrorType. Use Never if no failure is permitted.
    • completed: Indicates the stream finished successfully and no more values will be sent.
    • interrupted: Indicates the stream terminated due to cancellation (neither success nor failure).
  5. Explore Extended ReactiveSwift Modules

    master

    ReactiveSwift can be extended with several specialized modules:

    • ReactiveCocoa: Extends Cocoa frameworks and Objective-C runtime APIs with ReactiveSwift bindings.
    • Loop: Provides composable unidirectional data flow using ReactiveSwift.
    • ReactiveSwift Composable Architecture: Implements the Pointfree Composable Architecture using ReactiveSwift instead of Combine.
  6. Use Signals for continuous event streams

    master

    A signal (Signal) represents a series of events occurring over time.

    Key Characteristics:

    • Push-based: Signals are producer-driven. They represent streams already "in progress" (like user input or notifications).
    • Broadcast: All observers see the same events at the same time.
    • Passive: Observing a signal does not trigger side effects or start any work.
    • No Random Access: You can only evaluate events in the order they are sent.

    Signals can be manipulated using primitives like filter, map, reduce, and zip (which operates on multiple signals).

  7. Cancel work using Disposables

    master

    A disposable (Disposable) is a mechanism for memory management and cancellation.

    • From SignalProducers: start() returns a disposable. Disposing it cancels the work (e.g., network requests) and sends an interrupted event.
    • From Signals: Observing a signal returns a disposable. Disposing it stops the observer from receiving future events but does not affect the signal itself.
  8. Adhere to the Event serial and non-recursive guarantees

    master

    ReactiveSwift provides several guarantees regarding how events are delivered to observers:

    1. Serial Delivery: All events on a stream are guaranteed to arrive serially. An observer will never receive multiple Events concurrently, even if events are sent from multiple threads.
    2. No Recursive Delivery: Events are never delivered recursively. This means operators and observers do not need to be reentrant.
      • Warning: Sending a value event from a thread that is already processing a previous event from that same signal will result in a deadlock. This is intentional to prevent nondeterministic race conditions.
      • Exception: A terminal event is permitted to be sent recursively.
      • Workaround: If you need recursive signals, use a time-shifting operator like delay to ensure the event is not sent from an already-running handler.
    3. Synchronous by Default: ReactiveSwift does not introduce implicit concurrency. A "vanilla" signal or producer sends events synchronously; the observer is invoked immediately, and the underlying work does not resume until the event handler finishes.
  9. Implement custom ReactiveSwift operators

    master

    When implementing new operators, follow these guidelines to maintain API contracts and stability:

    • Target Signals for generality: Write operators for Signal whenever possible; SignalProducer will inherit them automatically via lifting.
    • Compose existing operators: Minimize custom logic by reusing built-in operators to reduce bugs and handle edge cases correctly.
    • Forward failures and interruptions: Propagate .failed and .interrupted events to the observer as soon as possible.
    • Switch over Event values: When creating custom observers, use a switch statement on the Event enum to ensure all cases (value, failed, completed, interrupted) are handled.
    • Avoid introducing concurrency: Operators should not perform work concurrently; leave concurrency management to the caller via Schedulers.
    • Avoid blocking: Operators should return a new signal or producer immediately. Any necessary work should be part of the event handling logic, not the operator invocation itself (except for specific synchronous operators like single() or wait()).
  10. Migrate Core Components from RxSwift to ReactiveSwift

    master

    When migrating from RxSwift, note that ReactiveSwift uses different primitives for managing state and streams. Key mappings include:

    • Observables: Use Signal for "hot" observables and SignalProducer for "cold" observables (which only emit values once a subscription starts).
    • Subjects: ReactiveSwift does not have a Subject type. Instead, use Signal.pipe(), which returns a tuple (output: Signal, input: Signal.Observer) used to both observe and send values.
    • State/Relays: Use Property or MutableProperty instead of BehaviorRelay or BehaviorSubject. MutableProperty is inherently error-free.
    • Disposables: Use CompositeDisposable instead of DisposeBag. Note that in ReactiveSwift, manual lifetime management of Disposables is often unnecessary as it is mostly automatic.
    • Completable/Single: These can be represented by a Signal or SignalProducer where the error type is Never.