### C# Observable Example (Rx) Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/RxComparison.md Illustrates a C# IObservable declaration. In Rx, it's impossible to determine from the signature alone whether subscribing will involve side effects or if each subscription triggers them. ```csharp IObservable Search(string query) ``` -------------------------------- ### Create and Start a SignalProducer Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt SignalProducer represents deferred work that creates signals on demand. Start a producer to execute its work and observe events. ```swift // Creating a SignalProducer let producer = SignalProducer { observer, lifetime in observer.send(value: 1) observer.send(value: 2) observer.sendCompleted() } // Starting a producer producer.start { event in print(event) } // Starting with specific handlers producer.startWithValues { value in print("Value: \(value)") } ``` -------------------------------- ### Start and Dispose SignalProducer Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/ReactivePrimitives.md Start a SignalProducer to create a Signal and handle its lifecycle. The deferred work is invoked when the producer is started. ```swift let frames: SignalProducer = vidStreamer.streamAsset(id: tvShowId) let interrupter = frames.start { frame in ... } interrupter.dispose() ``` -------------------------------- ### Vending Machine Implementation with Action Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/ReactivePrimitives.md An example of a VendingMachine class using ReactiveSwift's Action to handle purchases. The Action is configured with a state property (coins) and an enabledIf condition. It also observes successful sales. ```swift class VendingMachine { let purchase: Action let coins: MutableProperty // The vending machine is connected with a sales recorder. init(_ salesRecorder: SalesRecorder) { coins = MutableProperty(0) purchase = Action(state: coins, enabledIf: { $0 > 0 }) { coins, snackId in return SignalProducer { observer, _ in // The sales magic happens here. // Fetch a snack based on its id } } // The sales recorders are notified for any successful sales. purchase.values.observeValues(salesRecorder.record) } } ``` -------------------------------- ### Property Operators for Combining and Transforming Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt ReactiveSwift provides operators to transform and combine properties. Examples include map, filter, combineLatest, zip, and boolean operations. ```swift let count = MutableProperty(5) // Map let doubled = count.map { $0 * 2 } // Filter (with replacement) let evenOnly = count.filter(initial: 0) { $0 % 2 == 0 } // Skip repeats let unique = count.skipRepeats() // Combine latest let a = MutableProperty(1) let b = MutableProperty(2) let combined = Property.combineLatest(a, b).map { $0 + $1 } // Zip properties let zipped = Property.zip(a, b) // Boolean operations let isEnabled = MutableProperty(true) let isValid = MutableProperty(false) let canSubmit = isEnabled.and(isValid) let showWarning = isEnabled.or(isValid) let isDisabled = isEnabled.negate() // Check all/any conditions let allTrue = Property.all([isEnabled, isValid]) let anyTrue = Property.any([isEnabled, isValid]) ``` -------------------------------- ### Define a SignalProducer for search operations Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/APIContracts.md Encapsulate side effects within the producer to ensure work is only performed when the producer is started. ```swift func search(text: String) -> SignalProducer ``` -------------------------------- ### Recover from Errors with flatMapError Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Recovers from errors in a producer by starting a new producer. This is useful for transforming a producer that might fail into one that always succeeds. ```swift let producer = SignalProducer(error: .networkError) let recovered = producer.flatMapError { error in return SignalProducer(value: 0) } ``` -------------------------------- ### Inject Side Effects with SignalProducer.on in Swift Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Inject side effects into a SignalProducer at various stages (starting, started, event, value, failed, completed, interrupted, terminated, disposed) without altering the stream's values. The producer must be started for these effects to trigger. ```Swift let producer = signalProducer .on(starting: { print("Starting") }, started: { print("Started") }, event: { event in print("Event: \(event)") }, value: { value in print("Value: \(value)") }, failed: { error in print("Failed: \(error)") }, completed: { print("Completed") }, interrupted: { print("Interrupted") }, terminated: { print("Terminated") }, disposed: { print("Disposed") }) ``` -------------------------------- ### SignalProducer API Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt SignalProducer represents deferred work that creates a Signal on demand when started. It's suitable for operations like network requests. ```APIDOC ## SignalProducer ### Description SignalProducer represents deferred work that creates a new Signal each time it is started. This is ideal for operations like network requests. ### Creating a SignalProducer ```swift let producer = SignalProducer { observer, lifetime in observer.send(value: 1) observer.send(value: 2) observer.sendCompleted() } ``` ### Starting a Producer ```swift producer.start { event in print(event) } producer.startWithValues { value in print("Value: \(value)") } ``` ### Creating from various sources ```swift // From a value let singleValue = SignalProducer(value: "Hello") // From a sequence let sequence = SignalProducer([1, 2, 3, 4, 5]) // From a Result let result = SignalProducer(result: .success("Success")) // Empty and never producers let empty = SignalProducer.empty let never = SignalProducer.never ``` ``` -------------------------------- ### Retrieve Dependencies with Carthage Source: https://github.com/reactivecocoa/reactiveswift/blob/master/README.md Alternative command to fetch project dependencies when using Carthage. ```bash carthage checkout ``` -------------------------------- ### Initialize Git Submodules Source: https://github.com/reactivecocoa/reactiveswift/blob/master/README.md Initializes and updates submodules within the repository. ```bash git submodule update --init --recursive ``` -------------------------------- ### Create and Observe a Signal Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Use Signal for push-driven event streams. Create a signal with a pipe and observe its values or all events. ```swift // Creating a Signal with a pipe let (signal, observer) = Signal.pipe() // Sending values observer.send(value: 1) observer.send(value: 2) observer.sendCompleted() // Observing a Signal signal.observeValues { value in print("Received: \(value)") } // Observing all events signal.observe { event in switch event { case let .value(value): print("Value: \(value)") case let .failed(error): print("Error: \(error)") case .completed: print("Completed") case .interrupted: print("Interrupted") } } ``` -------------------------------- ### Purchase from Vending Machine with Action Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/ReactivePrimitives.md Demonstrates how to invoke an Action to purchase an item, handling success and failure results. Requires an initialized Action and a snack ID. ```swift vendingMachine.purchase .apply(snackId) .startWithResult { result in switch result { case let .success(snack): print("Snack: \(snack)") case let .failure(error): // Out of stock? Insufficient fund? print("Transaction aborted: \(error)") } } ``` -------------------------------- ### Order markup delimiters Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CONTRIBUTING.md Place 'precondition', 'parameters', and 'return' delimiters last in that specific order before the method signature. ```markdown /// DO: /// Create instance of `Foo` by passing it `Bar`. /// /// - note: The `foo` is not retained by the receiver. /// /// - parameters: /// - foo: Instance of `Foo`. init(foo: Foo) { /* ... */ /// DON'T /// Create counter that will count down from `number`. /// /// - parameters: /// - number: Number to count down from. /// /// - precondition: `number` must be non-negative. init(count: Int) ``` -------------------------------- ### Handle network failures Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/Example.OnlineSearch.md Demonstrates error handling by logging and returning an empty producer to prevent stream termination. ```swift .flatMap(.latest) { (query: String) -> SignalProducer<(Data, URLResponse), AnyError> in let request = self.makeSearchRequest(escapedQuery: query) return URLSession.shared.reactive .data(with: request) .flatMapError { error in print("Network error occurred: \(error)") return SignalProducer.empty } } ``` -------------------------------- ### ReactiveSwift Schedulers Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Demonstrates the usage of different schedulers provided by ReactiveSwift for controlling execution context, including main thread, background queues, and immediate execution. ```swift // Main thread scheduler let mainScheduler = UIScheduler() // Background queue scheduler let backgroundScheduler = QueueScheduler(qos: .background) // Immediate scheduler (synchronous) let immediateScheduler = ImmediateScheduler() // Using schedulers producer .start(on: backgroundScheduler) .observe(on: mainScheduler) .startWithValues { value in // Called on main thread } ``` -------------------------------- ### Initialize Signal with Lifetime Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CHANGELOG.md Shows the updated Signal initializer that uses Lifetime for resource management, replacing the obsolete Disposable-returning closure. ```swift // New: Add `Disposable`s to the `Lifetime`. let candies = Signal { (observer: Signal.Observer, lifetime: Lifetime) in lifetime += trickOrTreat.observe(observer) } // Obsolete: Returning a `Disposable`. let candies = Signal { (observer: Signal.Observer) -> Disposable? in return trickOrTreat.observe(observer) } ``` -------------------------------- ### Take First N Values Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Takes only the first 'n' values from a producer and then completes. Useful for scenarios where only initial data is needed. ```swift let producer = SignalProducer([1, 2, 3, 4, 5]) let firstTwo = producer.take(first: 2) // Emits: 1, 2, then completes ``` -------------------------------- ### ReactiveSwift Bindings Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Illustrates how to bind values to targets with automatic lifetime management using ReactiveSwift properties and operators. ```swift let label = UILabel() let text = MutableProperty("Hello") // One-way binding text.producer.startWithValues { label.text = $0 } // Using binding target text <~ otherProperty // Binding with operator label.reactive.text <~ text ``` -------------------------------- ### Use parameters delimiter Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CONTRIBUTING.md Always use the plural 'parameters' delimiter even for single-parameter functions. ```markdown /// DO: /// - parameters: /// - foo: Instance of `Foo`. /// DON'T: /// - parameter foo: Instance of `Foo`. ``` -------------------------------- ### Using Property Wrapper with MutableProperty Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CHANGELOG.md Demonstrates how to use `@MutableProperty` as a property wrapper for managing state within a class. Note that `Property` and `MutableProperty` are reference type containers and may not be suitable for types requiring value semantics. ```swift class ViewModel { @MutableProperty var count: Int = 0 func subscribe() { self.$count.producer.startWithValues { print("`count` has changed to \(count)") } } func increment() { print("count prior to increment: \(count)") self.$count.modify { $0 += 1 } } } ``` -------------------------------- ### Format Xcode markup lines Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CONTRIBUTING.md Expand lines to 80 characters and indent subsequent lines at the delimiter's colon position plus one space. ```markdown /// DO: /// For the sake of the demonstration we will use the lorem ipsum text here. /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ullamcorper /// tempor dolor a cras amet. /// /// - returns: Cras a convallis dolor, sed pellentesque mi. Integer suscipit /// fringilla turpis in bibendum volutpat. /// ... /// DON'T /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ullamcorper tempor dolor a cras amet. /// /// - returns: Cras a convallis dolor, sed pellentesque mi. Integer suscipit fringilla turpis in bibendum volutpat. /// ... /// DON'T II /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ullamcorper /// tempor dolor a cras amet. /// /// - returns: Cras a convallis dolor, sed pellentesque mi. Integer suscipit /// fringilla turpis in bibendum volutpat. ``` -------------------------------- ### Manage SignalProducer Resources with Lifetime Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CHANGELOG.md Use Lifetime to observe the disposal of a produced Signal. This pattern replaces older resource management techniques. ```swift let producer = SignalProducer { observer, lifetime in if let disposable = numbers.observe(observer) { lifetime.observeEnded(disposable.dispose) } } ``` -------------------------------- ### Format parameter descriptions Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CONTRIBUTING.md Treat parameter declarations as separate sentences or paragraphs. ```markdown /// DO: /// - parameters: /// - foo: A foo for the function. /// ... /// DON'T: /// - parameters: /// - foo: foo for the function; ``` -------------------------------- ### Add ReactiveSwift Dependency with Carthage Source: https://github.com/reactivecocoa/reactiveswift/blob/master/README.md To use ReactiveSwift with Carthage, add the specified line to your Cartfile. ```shell github "ReactiveCocoa/ReactiveSwift" ~> 6.1 ``` -------------------------------- ### Use code voice for symbols Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CONTRIBUTING.md Highlight symbols using backticks in descriptions, parameter definitions, and return statements. ```markdown /// DO: /// Create instance of `Foo` by passing it `Bar`. /// /// - parameters: /// - bar: Instance of `Bar`. /// ... /// DON'T: /// Create instance of Foo by passing it Bar. /// /// - parameters: /// - bar: Instance of Bar. ``` -------------------------------- ### Use active voice in documentation Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CONTRIBUTING.md Use the first person's active voice in the present simple tense. ```markdown /// DO: /// Do something magical and return pixie dust from `self`. /// /// DON'T: /// Does something magical and returns pixie dust from `self`. ``` -------------------------------- ### Variadic Sugar for Boolean Static Methods Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CHANGELOG.md Adds variadic sugar for boolean static methods like `Property.any`, allowing multiple boolean properties to be passed as arguments directly. ```swift Property.any(boolProperty1, boolProperty2, boolProperty3) ``` -------------------------------- ### Visualize flattening strategies Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Conceptual representation of how different flattening strategies interleave values over time. ```Swift let values = [ // imagine column offset as time [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8 ], ] let merge = [ 1, 4, 2, 7,5, 3,8,6 ] let concat = [ 1, 2, 3,4, 5, 6,7, 8] let latest = [ 1, 4, 7, 8 ] ``` -------------------------------- ### Manage Repeatable Work with Action Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Action handles availability and mutual exclusion for asynchronous tasks. It provides properties to observe execution state, enabled status, values, and errors. ```swift // Creating an Action let submitAction = Action { input in return SignalProducer { observer, _ in // Perform async work observer.send(value: true) observer.sendCompleted() } } // Applying the action submitAction.apply("data").startWithResult { result in switch result { case .success(let value): print("Success: \(value)") case .failure(let error): print("Error: \(error)") } } // Observing action state submitAction.isExecuting.producer.startWithValues { isExecuting in print("Is executing: \(isExecuting)") } submitAction.isEnabled.producer.startWithValues { isEnabled in print("Is enabled: \(isEnabled)") } // Observing values and errors submitAction.values.observeValues { value in print("Produced value: \(value)") } submitAction.errors.observeValues { error in print("Produced error: \(error)") } // Action with state let state = MutableProperty(nil) let userAction = Action(unwrapping: state) { user in return SignalProducer(value: user.name) } // Action enabled conditionally let isFormValid = MutableProperty(false) let saveAction = Action(enabledIf: isFormValid) { _ in return SignalProducer.empty } ``` -------------------------------- ### Create SignalProducers from Different Sources Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt SignalProducer can be created from a single value, a sequence, or a Result. Use .empty for a producer that never sends events, and .never for one that never completes. ```swift // Creating from a value let singleValue = SignalProducer(value: "Hello") // Creating from a sequence let sequence = SignalProducer([1, 2, 3, 4, 5]) // Creating from a Result let result = SignalProducer(result: .success("Success")) // Empty and never producers let empty = SignalProducer.empty let never = SignalProducer.never ``` -------------------------------- ### Using Property.any with Array of Booleans Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CHANGELOG.md Introduces the `any` operator for `Property` that accepts an array of boolean properties, returning a single property that is true if any of the input properties are true. ```swift let property = Property.any([boolProperty1, boolProperty2, boolProperty3]) ``` -------------------------------- ### Exclude return delimiter for initializers Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CONTRIBUTING.md Do not include a return delimiter in the markup for initializers. ```markdown /// DO: /// Initialises instance of `Foo` with given arguments. init(withBar bar: Bar = Bar.defaultBar()) { ... /// DON'T: /// Initialises instance of `Foo` with given arguments. /// /// - returns: Initialized `Foo` with default `Bar` init(withBar bar: Bar = Bar.defaultBar()) { ... ``` -------------------------------- ### Verify Signal Interruption Behavior Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CHANGELOG.md Demonstrates the expected behavior where manual interruption of a delayed producer discards outstanding events. ```swift // Completed upstream + `delay`. SignalProducer.empty .delay(10.0, on: QueueScheduler.main) .startWithCompleted { print("Value should have been discarded!") } .dispose() // Console(t+10): Value should have been discarded! ``` -------------------------------- ### Perform network requests for search Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/Example.OnlineSearch.md Transforms a signal of strings into a producer of search results using URLSession and flatMap(.latest) to ensure only the latest request is active. ```swift let searchResults = searchStrings .flatMap(.latest) { (query: String?) -> SignalProducer<(Data, URLResponse), AnyError> in let request = self.makeSearchRequest(escapedQuery: query) return URLSession.shared.reactive.data(with: request) } .map { (data, response) -> [SearchResult] in let string = String(data: data, encoding: .utf8)! return self.searchResults(fromJSONString: string) } .observe(on: UIScheduler()) ``` -------------------------------- ### Optional Left-Hand-Side Binding with <~ Operator Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CHANGELOG.md Illustrates the use of the `<~` binding operator with optional left-hand-side operands, which was previously not supported and required manual unwrapping. This change simplifies bindings in scenarios involving optional targets. ```swift let nilTarget: BindingTarget? = nil // This is now a valid binding. Previously required manual // unwrapping in ReactiveSwift 3.x. nilTarget <~ notifications.map { $0.count } ``` -------------------------------- ### Observe search results Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/Example.OnlineSearch.md Subscribes to the search results signal to handle value, error, and completion events. ```swift searchResults.observe { event in switch event { case let .value(results): print("Search results: \(results)") case let .failed(error): print("Search error: \(error)") case .completed, .interrupted: break } } ``` -------------------------------- ### Switching over Event values Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/APIContracts.md Use a switch statement on an Event to ensure all event types are handled, which allows the compiler to warn about missing cases. ```swift producer.start { event in switch event { case let .value(value): print("Value event: \(value)") case let .failed(error): print("Failed event: \(error)") case .completed: print("Completed event") case .interrupted: print("Interrupted event") } } ``` -------------------------------- ### Flattening Strategies for Inner Producers Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Strategies for handling nested signal producers using flatMap. ```swift let producer = SignalProducer([1, 2, 3]) let merged = producer.flatMap(.merge) { value in return SignalProducer(value: "Value: \(value)") .delay(Double(value), on: QueueScheduler.main) } // Emits values as each inner producer completes ``` ```swift let producer = SignalProducer([1, 2, 3]) let concatenated = producer.flatMap(.concat) { value in return SignalProducer(value: "Value: \(value)") } // Emits: "Value: 1", "Value: 2", "Value: 3" in order ``` ```swift let (signal, observer) = Signal.pipe() let latest = signal.flatMap(.latest) { value in return SignalProducer(value: "Value: \(value)") .delay(1.0, on: QueueScheduler.main) } // If new values arrive before delay completes, only the latest is forwarded ``` ```swift let producer = SignalProducer([1, 2, 3]) let raced = producer.flatMap(.race) { value in return SignalProducer(value: "Value: \(value)") .delay(Double(4 - value), on: QueueScheduler.main) } // Only emits from the producer that sends first ``` ```swift let (signal, observer) = Signal.pipe() let throttled = signal.flatMap(.throttle) { value in return SignalProducer(value: "Value: \(value)") .delay(1.0, on: QueueScheduler.main) } // Ignores values sent while the current inner producer is active ``` -------------------------------- ### Access Property Value and Observe Changes Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/ReactivePrimitives.md Access the current value of a Property and observe its changes through its associated Signal. Properties always hold a value and never fail. ```swift let currentTime: Property = video.currentTime print("Current time offset: \(currentTime.value)") currentTime.signal.observeValues { timeBar.timeLabel.text = "\($0)" } ``` -------------------------------- ### Create and Observe a Property Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Property represents observable state with a current value. Use MutableProperty for state that can change and observe its changes via its producer. ```swift // Creating a Property with an initial value let property = Property(value: 0) print(property.value) // Access current value: 0 // MutableProperty allows changes let mutableProperty = MutableProperty(0) mutableProperty.value = 42 print(mutableProperty.value) // 42 // Observing property changes mutableProperty.producer.startWithValues { value in print("New value: \(value)") } // Using the signal (doesn't include current value) mutableProperty.signal.observeValues { value in print("Changed to: \(value)") } // Modifying atomically mutableProperty.modify { value in value += 10 } // Swapping values let oldValue = mutableProperty.swap(100) ``` -------------------------------- ### Take Until Trigger Signal Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Takes values from a producer until a trigger signal fires. This allows for external cancellation or completion. ```swift let (trigger, triggerObserver) = Signal<(), Never>.pipe() let producer = SignalProducer.timer(interval: .seconds(1), on: QueueScheduler.main) let limited = producer.take(until: trigger) ``` -------------------------------- ### Take Events During a Lifetime Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Forwards events from a producer only during a specified lifetime. This helps manage resource cleanup. ```swift let lifetime = Lifetime.make() let producer = SignalProducer.timer(interval: .seconds(1), on: QueueScheduler.main) let limited = producer.take(during: lifetime.0) ``` -------------------------------- ### Perform failable transformations Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Uses attempt and attemptMap to handle operations that might fail within a SignalProducer chain. ```Swift let dictionaryPath = URL(fileURLWithPath: "/usr/share/dict/words") // Create a `SignalProducer` that lazily attempts the closure // whenever it is started let data = SignalProducer.attempt { try Data(contentsOf: dictionaryPath) } // Lazily apply a failable transformation let json = data.attemptMap { try JSONSerialization.jsonObject(with: $0) } json.startWithResult { result in switch result { case let .success(words): print("Dictionary as JSON:") print(words) case let .failure(error): print("Couldn't parse dictionary as JSON: \(error)") } } ``` -------------------------------- ### Concatenate Producers Sequentially Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Concatenates producers sequentially, ensuring values are emitted in the order they are defined. ```swift let first = SignalProducer([1, 2]) let second = SignalProducer([3, 4]) first.concat(second).startWithValues { value in print(value) } // Emits: 1, 2, 3, 4 (in order) ``` -------------------------------- ### Controlling Observation Scope with Lifetime Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/ReactivePrimitives.md Shows how to use Lifetime to limit the scope of a SignalProducer's observation. The `take(during:)` operator ensures that the producer stops emitting values once the lifetime ends, useful for managing resources like video streams. ```swift class VideoPlayer { private let (lifetime, token) = Lifetime.make() func play() { let frames: SignalProducer = ... frames.take(during: lifetime).start { frame in ... } } } ``` -------------------------------- ### Observe Specific Signal Events in Swift Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Observe individual events (values, failures, completion, interruption) from a Signal using dedicated observer functions. Use this when you only need to react to specific event types. ```Swift signal.observeValues { value in print("Value: \(value)") } signal.observeFailed { error in print("Failed: \(error)") } signal.observeCompleted { print("Completed") } signal.observeInterrupted { print("Interrupted") } ``` -------------------------------- ### Add ReactiveSwift Dependency with Swift Package Manager Source: https://github.com/reactivecocoa/reactiveswift/blob/master/README.md To use ReactiveSwift with Swift Package Manager, add the specified package to your Package.swift file. ```swift .package(url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", from: "6.1.0") ``` -------------------------------- ### Zip multiple streams pair-wise Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Joins values from multiple streams into tuples, where the Nth tuple contains the Nth elements from each input stream. ```Swift let (numbersSignal, numbersObserver) = Signal.pipe() let (lettersSignal, lettersObserver) = Signal.pipe() let signal = Signal.zip(numbersSignal, lettersSignal) signal.observeValues { next in print("Next: \(next)") } signal.observeCompleted { print("Completed") } numbersObserver.send(value: 0) // nothing printed numbersObserver.send(value: 1) // nothing printed lettersObserver.send(value: "A") // prints (0, A) numbersObserver.send(value: 2) // nothing printed numbersObserver.sendCompleted() // nothing printed lettersObserver.send(value: "B") // prints (1, B) lettersObserver.send(value: "C") // prints (2, C) & "Completed" ``` -------------------------------- ### Add spacing to markup delimiters Source: https://github.com/reactivecocoa/reactiveswift/blob/master/CONTRIBUTING.md Include one line between markup delimiters and avoid whitespace lines between parameters. ```markdown /// DO: /// - note: This is an amazing function. /// /// - parameters: /// - foo: Instance of `Foo`. /// - bar: Instance of `Bar`. /// /// - returns: Something magical. /// ... /// DON'T: /// - note: Don't forget to breathe, it's important! 😎 /// - parameters: /// - foo: Instance of `Foo`. /// - bar: Instance of `Bar`. /// - returns: Something claustrophobic. ``` -------------------------------- ### Combine Multiple Signals Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Operators to aggregate values from multiple signal producers. ```swift let a = SignalProducer([1, 2]) let b = SignalProducer(["A", "B"]) SignalProducer.combineLatest(a, b).startWithValues { int, string in print("\(int), \(string)") } // Emits pairs with latest values from both ``` ```swift let a = SignalProducer([1, 2, 3]) let b = SignalProducer(["A", "B", "C"]) SignalProducer.zip(a, b).startWithValues { int, string in print("\(int), \(string)") } // Emits: (1, "A"), (2, "B"), (3, "C") ``` -------------------------------- ### Skip First N Values Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Skips the first 'n' values emitted by a producer and forwards the rest. Useful for ignoring initial or irrelevant data. ```swift let producer = SignalProducer([1, 2, 3, 4, 5]) let skipped = producer.skip(first: 2) // Emits: 3, 4, 5 ``` -------------------------------- ### Retry Producer on Failure Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Retries the producer a specified number of times if it fails. Useful for transient network errors. ```swift let producer = makeNetworkRequest() let retried = producer.retry(upTo: 3) ``` -------------------------------- ### Signal API Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Signal represents a push-driven stream of events over time. It can emit zero or more values and must terminate with a single event (completed, failed, or interrupted). ```APIDOC ## Signal ### Description Signal is a push-driven stream that sends events over time, parameterized by the type of values being sent and the type of failure that can occur. ### Creating a Signal with a pipe ```swift let (signal, observer) = Signal.pipe() ``` ### Sending Events ```swift observer.send(value: 1) observer.send(value: 2) observer.sendCompleted() ``` ### Observing a Signal ```swift signal.observeValues { value in print("Received: \(value)") } signal.observe { event in switch event { case let .value(value): print("Value: \(value)") case let .failed(error): print("Error: \(error)") case .completed: print("Completed") case .interrupted: print("Interrupted") } } ``` ``` -------------------------------- ### Observe Signal Events in Swift Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Observe all events (value, failed, completed, interrupted) from a Signal using a switch statement. This is useful for handling all possible outcomes of a signal. ```Swift signal.observe { event in switch event { case let .value(value): print("Value: \(value)") case let .failed(error): print("Failed: \(error)") case .completed: print("Completed") case .interrupted: print("Interrupted") } } ``` -------------------------------- ### Property Operators API Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt This section details common operators used with ReactiveSwift Properties for transforming and combining observable values. ```APIDOC ## Property Operators ### Description Operators for transforming and combining Property values. ### Map ```swift let count = MutableProperty(5) let doubled = count.map { $0 * 2 } ``` ### Filter ```swift let evenOnly = count.filter(initial: 0) { $0 % 2 == 0 } ``` ### Skip Repeats ```swift let unique = count.skipRepeats() ``` ### Combine Latest ```swift let a = MutableProperty(1) let b = MutableProperty(2) let combined = Property.combineLatest(a, b).map { $0 + $1 } ``` ### Zip Properties ```swift let zipped = Property.zip(a, b) ``` ### Boolean Operations ```swift let isEnabled = MutableProperty(true) let isValid = MutableProperty(false) let canSubmit = isEnabled.and(isValid) let showWarning = isEnabled.or(isValid) let isDisabled = isEnabled.negate() ``` ### Check All/Any Conditions ```swift let allTrue = Property.all([isEnabled, isValid]) let anyTrue = Property.any([isEnabled, isValid]) ``` ``` -------------------------------- ### Retry network requests Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/Example.OnlineSearch.md Combines retry logic with error handling to improve robustness of the search stream. ```swift let searchResults = searchStrings .flatMap(.latest) { (query: String) -> SignalProducer<(Data, URLResponse), AnyError> in let request = self.makeSearchRequest(escapedQuery: query) return URLSession.shared.reactive .data(with: request) .retry(upTo: 2) .flatMapError { error in print("Network error occurred: \(error)") return SignalProducer.empty } } .map { (data, response) -> [SearchResult] in let string = String(data: data, encoding: .utf8)! return self.searchResults(fromJSONString: string) } .observe(on: UIScheduler()) ``` -------------------------------- ### Add ReactiveSwift Dependency with CocoaPods Source: https://github.com/reactivecocoa/reactiveswift/blob/master/README.md To use ReactiveSwift with CocoaPods, add the specified line to your Podfile. ```ruby pod 'ReactiveSwift', '~> 6.1' ``` -------------------------------- ### Log ReactiveSwift Events with `logEvents()` Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/DebuggingTechniques.md Use the `logEvents()` operator to print events from a signal producer to standard output for debugging. This operator can be configured with a custom logger function for conditional logging, such as only in DEBUG builds. ```swift let property = MutableProperty("") ... let searchString = property.producer .throttle(0.5, on: QueueScheduler.main) .logEvents() ``` ```swift func debugLog(identifier: String, event: String, fileName: String, functionName: String, lineNumber: Int) { // Don't forget to set up the DEBUG symbol (http://stackoverflow.com/a/24112024/491239) #if DEBUG print(event) #endif } let property = MutableProperty("") ... let searchString = property.producer .throttle(0.5, on: QueueScheduler.main) .logEvents(logger: debugLog) ``` ```swift let property = MutableProperty("") ... let searchString = property.producer .throttle(0.5, on: QueueScheduler.main) .logEvents(identifier: "✨My awesome stream ✨") ``` ```swift let property = MutableProperty("") ... let searchString = property.producer .throttle(0.5, on: QueueScheduler.main) .logEvents(events: [.disposed]) // This will happen when `property` is released ``` -------------------------------- ### Throttle search requests Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/Example.OnlineSearch.md Limits the frequency of search requests by applying the throttle operator to the input signal. ```swift let searchStrings = textField.reactive.continuousTextValues .throttle(0.5, on: QueueScheduler.main) ``` -------------------------------- ### Debug streams with logEvents Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/Example.OnlineSearch.md Uses the built-in logEvents operator to automatically log stream events. ```swift let searchString = textField.reactive.continuousTextValues .throttle(0.5, on: QueueScheduler.main) .logEvents() ``` -------------------------------- ### Observe Signal Events Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/ReactivePrimitives.md Observe values emitted by a Signal. The owner of a Signal has unilateral control over the event stream. ```swift let channel: Signal = tvStation.channelOne channel.observeValues { program in ... } ``` -------------------------------- ### Aggregate stream values with reduce Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Reduces a stream's values into a single combined value, emitted only after the input stream completes. ```Swift let (signal, observer) = Signal.pipe() signal .reduce(1) { $0 * $1 } .observeValues { value in print(value) } observer.send(value: 1) // nothing printed observer.send(value: 2) // nothing printed observer.send(value: 3) // nothing printed observer.sendCompleted() // prints 6 ``` -------------------------------- ### Catch failures with flatMapError Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Catches failures on an input stream and replaces them with a new SignalProducer. ```Swift let (signal, observer) = Signal.pipe() let producer = SignalProducer(signal) let error = NSError(domain: "domain", code: 0, userInfo: nil) producer .flatMapError { _ in SignalProducer(value: "Default") } .startWithValues { print($0) } observer.send(value: "First") // prints "First" observer.send(value: "Second") // prints "Second" observer.send(error: error) // prints "Default" ``` -------------------------------- ### Merge Multiple Signals into One Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Merges multiple signals into a single signal. The order of emitted values may vary. ```swift let a = SignalProducer([1, 2]) let b = SignalProducer([3, 4]) SignalProducer.merge([a, b]).startWithValues { value in print(value) } // Emits: 1, 2, 3, 4 (order may vary) ``` -------------------------------- ### Observe text field edits Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/Example.OnlineSearch.md Uses the ReactiveCocoa extension for UITextField to create a signal of continuous text values. ```swift let searchStrings = textField.reactive.continuousTextValues ``` -------------------------------- ### Debug streams with side effects Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/Example.OnlineSearch.md Injects a print statement into the stream to observe events without altering stream behavior. ```swift let searchString = textField.reactive.continuousTextValues .throttle(0.5, on: QueueScheduler.main) .on(event: { print ($0) }) // the side effect ``` -------------------------------- ### Delay Signal Events Source: https://context7.com/reactivecocoa/reactiveswift/llms.txt Delays all events from a producer by a specified time interval on a given scheduler. ```swift let producer = SignalProducer([1, 2, 3]) let delayed = producer.delay(1.0, on: QueueScheduler.main) ``` -------------------------------- ### Event Stream Grammar Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/APIContracts.md Defines the valid sequence of events in an event stream: zero or more values followed by an optional terminating event (interrupted, failed, or completed). No further events are sent after a terminating event. ```plaintext value* (interrupted | failed | completed)? ``` -------------------------------- ### Aggregate stream values with collect Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/BasicOperators.md Collects all values from a stream into a single array, emitted only after the input stream completes. ```Swift let (signal, observer) = Signal.pipe() signal .collect() .observeValues { value in print(value) } observer.send(value: 1) // nothing printed observer.send(value: 2) // nothing printed observer.send(value: 3) // nothing printed observer.sendCompleted() // prints [1, 2, 3] ``` -------------------------------- ### Break Apart Signal Chains for Swift Compiler Errors Source: https://github.com/reactivecocoa/reactiveswift/blob/master/Documentation/DebuggingTechniques.md When encountering misleading Swift compiler errors in signal chains, break the chain apart and add explicit type definitions to pinpoint the exact location of the error. ```swift SignalProducer(value:42) .on(value: { answer in return _ }) .startWithCompleted { print("Completed.") } ``` ```swift let initialProducer = SignalProducer.init(value:42) let sideEffectProducer = initialProducer.on(value: { (answer: Int) in return _ }) let disposable = sideEffectProducer.startWithCompleted { print("Completed.") } ```