Streams of values over time

Overview

ReactiveSwift

Streams of values over time. Tailored for Swift.

Latest ReactiveSwift Documentation Join the ReactiveSwift Slack community.


Carthage compatible CocoaPods compatible SwiftPM compatible GitHub release Swift 5.1 platforms

đźš„ Release Roadmap

Getting Started

Learn about the Core Reactive Primitives in ReactiveSwift, and Basic Operators available offered by these primitives.

Extended modules

Module Repository Description
ReactiveCocoa ReactiveCocoa/ReactiveCocoa

Extend Cocoa frameworks and Objective-C runtime APIs with ReactiveSwift bindings and extensions.

Loop ReactiveCocoa/Loop

Composable unidirectional data flow with ReactiveSwift.

ReactiveSwift Composable Architecture trading-point/reactiveswift-composable-architecture

The Pointfree Composable Architecture using ReactiveSwift instead of Combine.

What is ReactiveSwift in a nutshell?

ReactiveSwift offers composable, declarative and flexible primitives that are built around the grand concept of streams of values over time.

These primitives can be used to uniformly represent common Cocoa and generic programming patterns that are fundamentally an act of observation, e.g. delegate pattern, callback closures, notifications, control actions, responder chain events, futures/promises and key-value observing (KVO).

Because all of these different mechanisms can be represented in the same way, it’s easy to declaratively compose them together, with less spaghetti code and state to bridge the gap.

References

  1. API Reference

  2. API Contracts

    Contracts of the ReactiveSwift primitives, Best Practices with ReactiveSwift, and Guidelines on implementing custom operators.

  3. Debugging Techniques

  4. RxSwift Migration Cheatsheet

Installation

ReactiveSwift supports macOS 10.9+, iOS 9.0+, watchOS 2.0+, tvOS 9.0+ and Linux.

Carthage

If you use Carthage to manage your dependencies, simply add ReactiveSwift to your Cartfile:

github "ReactiveCocoa/ReactiveSwift" ~> 6.1

If you use Carthage to build your dependencies, make sure you have added ReactiveSwift.framework to the "Linked Frameworks and Libraries" section of your target, and have included them in your Carthage framework copying build phase.

CocoaPods

If you use CocoaPods to manage your dependencies, simply add ReactiveSwift to your Podfile:

pod 'ReactiveSwift', '~> 6.1'

Swift Package Manager

If you use Swift Package Manager, simply add ReactiveSwift as a dependency of your package in Package.swift:

.package(url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", from: "6.1.0")

Git submodule

  1. Add the ReactiveSwift repository as a submodule of your application’s repository.
  2. Run git submodule update --init --recursive from within the ReactiveCocoa folder.
  3. Drag and drop ReactiveSwift.xcodeproj into your application’s Xcode project or workspace.
  4. On the “General” tab of your application target’s settings, add ReactiveSwift.framework to the “Embedded Binaries” section.
  5. If your application target does not contain Swift code at all, you should also set the EMBEDDED_CONTENT_CONTAINS_SWIFT build setting to “Yes”.

Playground

We also provide a Playground, so you can get used to ReactiveCocoa's operators. In order to start using it:

  1. Clone the ReactiveSwift repository.
  2. Retrieve the project dependencies using one of the following terminal commands from the ReactiveSwift project root directory:
    • git submodule update --init --recursive OR, if you have Carthage installed
    • carthage checkout
  3. Open ReactiveSwift.xcworkspace
  4. Build ReactiveSwift-macOS scheme
  5. Finally open the ReactiveSwift.playground
  6. Choose View > Show Debug Area

Have a question?

If you need any help, please visit our GitHub issues or Stack Overflow. Feel free to file an issue if you do not manage to find any solution from the archives.

Release Roadmap

Current Stable Release:
GitHub release

Plan of Record

ABI stability release

ReactiveSwift has no plan to declare ABI and module stability at the moment. It will continue to be offered as a source only dependency for the foreseeable future.

Comments
  • Stream of one event.

    Stream of one event.

    aka Single #201 or (lazy?) Promise or (lazy?) Future. Prototype

    The RAC team is considering moving this forward. Apparently we would be able to provide a more concise API on top of the stronger compiler guarantees, and it is observed that the value-or-failure are quite commonly used, especially in modelling network requests or API queries.

    A few design decisions need to be discussed:

    1. Should it be cold or "warm"?

      Proposal: Cold by default, opt-in replay via replayLazily()?

    2. Should it be called Promise or Future if it isn't "warm" by default?

    3. How should we model the event?

      Proposal:

      extension Promise {
          public enum Event {
               case completed(Value)
               case failed(Error)
               case interrupted
          }
      }
      
    4. Should we support operator lifting as part of the public API? It can be made safe if we always apply take(last: 1) as part of the lifting.

    work in progress 
    opened by andersio 50
  • SignalProducer on background scheduler not sending value events.

    SignalProducer on background scheduler not sending value events.

    I'm currently developing an app, and the API server isn't ready yet, so I'm trying to mock the API calls.

    I'm having trouble, and I'd be very grateful for some help.

    Here's basically what the API Manager looks like:

    class ApiManager {
        static let shared = ApiManager()
        private let scheduler = QueueScheduler(qos: .background, name: "MyProject.ApiManager")
        
        func getDataA() -> SignalProducer<[MyData], NoError> {
            return self.mockGetData(count: 1, delay: 1)
        }
        func getDataB() -> SignalProducer<[MyData], NoError> {
            return self.mockGetData(count: 2, delay: 1)
        }
        func getDataC() -> SignalProducer<[MyData], NoError> {
            return self.mockGetData(count: 3, delay: 1)
        }
        
        private func mockGetData(count: Int, delay: TimeInterval) -> SignalProducer<[MyData], NoError> {
            return SignalProducer<[MyData], NoError> { observer, lifetime in
                var dataItems = [MyData]()
                
                for _ in 1 ... count {
                    let myData = DataCache.shared.randomDataItem() // Simply gets a random item from an array
                    dataItems.append(myData)
                }
                
                observer.send(value: dataItems)
                observer.sendCompleted()
            }
            .delay(delay, on: self.scheduler)
        }
    }
    

    In another place, I attempt to get one array of items from each A, B, and C. That looks something like this.

    // Inside a class:
    
    // self.shouldGetDataProperty is of type MutableProperty<()>
    self.shouldGetDataProperty.signal
        .flatMap(.latest) { () -> SignalProducer<([MyData], [MyData], [MyData]), NoError> in
            return SignalProducer.zip(
                ApiManager.shared.getDataA(), // Sometimes terminates without values
                ApiManager.shared.getDataB(), // Sometimes terminates without values
                ApiManager.shared.getDataC() // Sometimes terminates without values
            )
        }
        .map { dataA, dataB, dataC in
            // Sometimes, this closure is not called.
            
            // Map and continue processing...
        }
    

    My problem, as I wrote in the comments, is that sometimes (about 5%) one or more of the the zipped SignalProducers doesn't return values, canceling the zip.

    If I don't delay the signal producers in ApiManager, then this never happens. So, I suspect I'm doing something wrong with the QueueScheduler.

    I tried logging events on each SignalProducer individually. When I do that, I typically get an event log like this:

    A: Starting A: Started B: Starting B: Started C: Starting C: Started A: Value [...] A: Completed A: Terminated A: Disposed B: Value [...] B: Completed B: Terminated B: Disposed C: Completed C: Terminated C: Disposed

    In that example, SignalProducer C didn't send a Value event, despite that fact that a value had been sent to the Observer in the SignalProducer's initialization closure.

    What could I have done wrong to make the SignalProducer behave this way?

    opened by ABeard89 27
  • `Lifetime`-based producer resource management

    `Lifetime`-based producer resource management

    In RAS 1.0 and earlier, the start handler is passed a CompositeDisposable directly. While it is not an intended way to interrupt the producer, disposing of it can often, but not always, yield similar results as sending terminal events. It generally works only if the produced Signal has an upstream to be interrupted in the first place.

    Related test case: https://github.com/ReactiveCocoa/ReactiveSwift/pull/334/commits/5d01764087fac7aed63d98bbc554f484d4023141#diff-9cd786f9e52e786771d96cf8c42d3befL34

    The PR proposes to close this unreliable semantic hole by using Lifetime instead.

    init(_ startHandler: @escaping (Signal<Value, Error>.Observer, Lifetime) -> Void)
    

    Alternative

    The start handler may instead follow Signal.init to be (Observer<Value, Error>) -> Disposable?. While it achieves the same goal without requiring a new type, this however cannot be migrated due to tuple splat messing with overloading.

    Possible follow-up

    If this gets accepted, we may consider matching the generator closure of Signal.init with this for consistency. However, like the alternative above, such change cannot be migrated. That said it is expected to have less impact, since Signal.pipe is the more popular API while Signal.init is primarily used by operators.

    opened by andersio 22
  • Add initialisers to create an Action from an input property

    Add initialisers to create an Action from an input property

    Update: Closes #88.


    PropertyAction encapsulates the pattern where an Action should be enabled only if its input is non-nil.

    The prime example of this pattern is form validation: validate some input text, and store the validated results in a property. If the form is valid, the property will be non-nil, and it should be safe to grab the current value and submit the form.

    I've personally written a bunch of Action-based code that basically just implemented this logic in an ad-hoc fashion, so I think it would be super useful to have a convenient shorthand for it.


    Ideally this could just be a convenience initialiser on Action:

    extension Action where Input == Void {
      // ...
    }
    

    But unfortunately this triggers Swift's "same-type requirement makes generic parameter non-generic" error.

    opened by sharplet 22
  • Refactor Github Actions to cover more swift versions

    Refactor Github Actions to cover more swift versions

    • Test against Xcode 14.1 and 13.4.1
    • Use setup-swift action to install specific swift versions (replaces swiftenv script)
    • Test against Swift 5.2 and 5.7

    Checklist

    • [x] Updated CHANGELOG.md.
    opened by braker1nine 21
  • Deadlock

    Deadlock

    Hi,

    I am running into a deadlock issue. I’m not entirely sure why it is happening yet. Here is my setup (dumbed down as this is the only part breaking, can provide more if needed).

    class ActionController {
    	var delay: NSTimeInterval = 0.0
    	let undoable = MutableProperty<Bool>(false)
    
    	func start() {
    		if delay > 0.0 {
    			undoable.value = true
    		}
    		
    		// More stuff
    		// Eventually will commit once delay is hit
    		// Can provide more if needed.
    	}
    	
    	func undo() {
    		guard undoable.value else {
    			return
    		}
    		
    		// Do some stuff
    		
    		/***** DEADLOCK HAPPENS ON LINE BELOW *******/
    		undoable.value = false
    		/********************************************/
    	}
    }
    
    class MyViewModel {
    
    	private let currentAction = MutableProperty<ActionController?>(nil)
    	
    	let undoEnabled = MutableProperty<Bool>(false)
    	
    	init() {
    		undoEnabled <~ currentAction.producer
    			.flatMap(.Concat) { action in
    				guard let action = action else {
    					return SignalProducer<Bool, NoError>(value: false)
    				}
    				
    				return action.undoable.producer
    			}
    			.skipRepeats()
    	}
    	
    	func commitAction() {
    		let action = ActionController()
    		action.delay = 10
    		action.start()
    	}
    	
    	func undoCurrentAction() {
    		currentAction.value?.undo()
    	}
    
    	 func onActionCompleted() {
    		// Method gets called when ActionController completes    
    		currentAction.value = nil
    	}
    
    }
    

    Both commitAction() and undoCurrentAction() get called from a UIViewController that the MyViewModel is powering and has subscribers to undoEnabled.

    Example for testing:

            viewModel.undoEnabled.producer.startWithNext { [unowned self] enabled in
                if enabled {
                    self.viewModel.undoCurrentAction()
                }
            }
    

    The deadlock seems to be happening when calling undo and setting undoable’s value to false.

    opened by codyrobb 20
  • Swift 4.1 migration

    Swift 4.1 migration

    Last updated and tested on: Xcode 9.3 GM.

    Checklist

    • [x] Updated CHANGELOG.md.
    • [x] Remove BindingSource workarounds
    • [x] Make Signal.Event and ActionError Equatable
    • [x] .flatMap -> .compactMap
    • [x] Remove no longer necessary Result.materialize extension
    • [x] Wait for Xcode 9.3
    • [x] Update Travis
    • [x] ~~Tag final Result release~~ Can be done separately.
    • [x] ~~Wait for fix to .logEvents regression~~ -> Workaround is implemented, doesn't seem like they'll fix the regression.
    • [x] Maintain Swift 4.0.x compatibility using #if swift(>=4.1)
    • [x] Verify UnsafeMutablePointer deprecation changes (I'm not totally sure about them)
    opened by NachoSoto 19
  • Pitch: Deprecate ActionProtocol

    Pitch: Deprecate ActionProtocol

    ...instead of removing it completely. See the discussion on #245 for context. I'm proposing this change as an alternative for discussion: there are some issues with this approach, so I thought it would be good to have something concrete to discuss.

    Benefits:

    • Mergeable into master now, suitable for inclusion in the next minor release.
    • ActionProtocol is an implementation detail, but isn't clearly documented as such. There are possibly users making use of it in ways we didn't intend (I was once one of them).

    Update: See https://github.com/ReactiveCocoa/ReactiveSwift/pull/248#issuecomment-277496797.

    Downsides:
    • Because conditionally compiled code has to be syntactically valid, we essentially have to duplicate the extension. I experimented with using an internal typealias to work around this limitation, but it was unfortunately a dead-end.

    I don't have much of a problem with the amount of duplication in this case. But it's pretty clear to me that this approach won't scale all that well to SignalProtocol and SignalProducerProtocol, whose extensions currently house all of the operator definitions. There would be a lot of duplication. There are certainly techniques we could use to avoid duplicating the implementations (reducing the duplication to declarations only), but they might not be pretty.

    opened by sharplet 19
  • Add `FlattenStrategy.race`

    Add `FlattenStrategy.race`

    Implemented https://github.com/ReactiveCocoa/ReactiveSwift/issues/138.

    Ref: ReactiveX - Amb operator

    I'm still wondering whether .first is really a good naming since there's already a blocking func first(). I personally feel race is a better name.

    opened by inamiy 19
  • Include KeyPath subscripts on Property types

    Include KeyPath subscripts on Property types

    I think it'd make sense to include a way to create a new Property or BindingTarget from a Property with a KeyPath.

    struct User {
      var name: String
    }
    
    let property = MutableProperty(User(name: "a"))
    property[\.name] <~ someBindingSource
    

    This is awkward to express otherwise. You can't really use <~ and are forced to observe the values manually.

    I'd suggest making the subscript return a property, except that (1) this might make the ownership difficult to work out and (2) I'm not sure if we can express the Property/MutableProperty relationship in Swift's type system. But if it is possible, then it'd be nice.

    help wanted good first step proposal 
    opened by mdiep 17
  • Add @Observable property wrapper and bump the CI to Xcode 11 / Swift 5.1

    Add @Observable property wrapper and bump the CI to Xcode 11 / Swift 5.1

    Checklist

    • [x] Updated CHANGELOG.md.

    turn this

    class ViewModel {
        private(set) lazy var profile = Property<Profile>(mutableProfile)
        private let mutableProfile: MutableProperty<Profile>
    
        init(profile: Profile) {
            mutableProfile = MutableProperty<Profile>(profile)
        }
    }
    

    into this

    class ViewModel {
        @Observable private(set) var profile: Profile
    
        init(profile: Profile) {
            self.profile = profile
        }
    }
    

    usage

    viewModelInstance.profile.$property.signal.observeValues { value in
        // ....
    {
    
    opened by petrpavlik 16
  • Is it planned to add count argument to `collect(every:on:skipEmpty:discardWhenCompleted:)`?

    Is it planned to add count argument to `collect(every:on:skipEmpty:discardWhenCompleted:)`?

    opened by ChaseChoi 0
  • [BUG] XCode 14 beta 3 - bitcode issue

    [BUG] XCode 14 beta 3 - bitcode issue

    Hi I have a problem with XCode 14 about bitcode.

    XCode tells me to wait for an update for the package, I have already updated ReactiveCocoa and ReactiveSwift to the latest SPM versions

    Screenshot 2022-07-22 at 13 37 38

    Works fine on simulatore but not on physical device

    Do you have any news about it?

    Thanks

    opened by salvatoreboemia 1
  • [WIP] `Sendable` support

    [WIP] `Sendable` support

    This is probably all sorts of wrong (especially the @unchecked Sendable).

    It also fails to compile with no more errors, so I don't know what else I need to fix 🤷🏻 (I filed FB10544343 for this) Screenshot 2022-07-03 at 18 08 32

    Compiling with swift build produces no errors either, but echo $? returns 1.

    Yup, this adds the word "sendable" 138 times đź‘€

    blocked source breaking 
    opened by NachoSoto 0
  • Add `asyncStream` and `asyncThrowingStream` for `Signal` and `SignalProducer`

    Add `asyncStream` and `asyncThrowingStream` for `Signal` and `SignalProducer`

    This is a proposal to add asyncStream and asyncThrowingStream in order to bridge into Swift Concurrency. I find this especially useful for writing non-blocking async tests.

    A couple of things I'd love to hear your thoughts on (apart from the usual review):

    • General thoughts on the idea
    • Where to place these extensions within the project and naming of files
    • Raising of CI platform to Xcode 11 (due to minimum Swift and testing target version requirements)
    • Lack of support for Swift Concurrency in Quick/Nimble (leading to tests written with XCTest)

    Note: Mac Catalyst builds are failing to launch on pre-monterey macOS versions: There is a workaround described in the documents but probably not worth implementing in the CI. More info here.

    Mac Catalyst apps that use Swift Concurrency may fail to launch on an operating system prior to macOS Monterey. (84393581)

    blocked work in progress 
    opened by Marcocanc 1
  • xCode13 CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler

    xCode13 CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler

    Hello, just ran into this with SPM :

    https://developer.apple.com/documentation/Xcode-Release-Notes/xcode-13-release-notes

    Swift libraries depending on Combine may fail to build for targets including armv7 and i386 architectures. (82183186, 82189214)

    Workaround: Use an updated version of the library that isn’t impacted (if available) or remove armv7 and i386 support

    CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler (in target 'ReactiveSwift' from project 'ReactiveSwift')

    opened by PierreBrisorgueil 0
Releases(7.1.0)
  • 7.1.0(Dec 12, 2022)

    This the first minor release of ReactiveSwift 7.

    The minimum deployment targets for Apple OSes have been increased to iOS 10, macOS 10.12, tvOS 10 and watchOS 3. If you need to support older OS versions, please continue to use 7.0.0.

    Changes

    1. Add CI Release jobs on tag push (#862, kudos to @p4checo)
    2. Fix some issues related to locking, bumped min OS versions to iOS 10, macOS 10.12, tvOS 10, watchOS 3 (#859, kudos to @mluisbrown)
    3. Add async helpers to Schedulers (#857, kudos to @p4checo)
    4. Add primary associated types to SignalProducerConvertible & SignalProducerProtocol (#855, kudos to @braker1nine)
    5. Refactor Github Actions to cover more swift versions (#858, kudos to @braker1nine)
    6. Use OSAllocatedUnfairLock instead of os_unfair_lock on supported Apple platforms (#856, kudos to @mluisbrown)
    Source code(tar.gz)
    Source code(zip)
  • 7.0.0(Nov 19, 2021)

    This is the first release of ReactiveSwift 7.0. It has a couple of minor breaking changes in both ABI and source over ReactiveSwift 6.0.

    Changes

    1. The UnidirectionalBinding operator <~ returns non optional values. (#834, kudos to @NicholasTD07)

    2. Fixed issue where SingalProducer.try(upTo:interval:count:) shares state between invocation of start on the same producer. (#829, kudos to @sebastiangrail)

    3. Signal.Event is now marked as frozen enum. (#841, kudos to @NachoSoto)

    Source code(tar.gz)
    Source code(zip)
  • 6.7.0(Sep 3, 2021)

    This is the seventh minor release of ReactiveSwift 6.

    Additions

    1. Signal offers two special variants for advanced users: unserialized and reentrant-unserialized. (#797)

      The input observer of these variants assume that mutual exclusion has been enforced by its callers.

      You can create these variants through four Signal static methods: unserialized(_:), unserializedPipe(_:), reentrantUnserialized(_:) and reentrantUnserializedPipe(_:). These would be adopted by ReactiveCocoa UIKit bindings to improve interoperability with Loop, to tackle some legitimate recursive delivery scenarios (e.g. around first responder management), and also to reduce fine-grained locking in ReactiveCocoa.

      Note that the default behavior of Signal has not been changed — event serialization remains the default behavior.

    2. SignalProducer offers an unserialized variant via SignalProducer.unserialized(_:). (#797)

    3. TestScheduler can now advanced its clock by TimeInterval. (#828, kudos to @carsten-wenderdel)

    Changes

    1. Signal and Properties now use fewer locks, which should translate into minor performance improvements. (#797)

    2. Fixed spelling error in Lifetime.Token class documentation. (#835, kudos to @ansonj)

    3. As a continued refactoring effort since ReactiveSwift 6.6.0, all unary Signal and SignalProducer operators have been migrated to a new internal representation.

      When debugging your application, the call stacks involving ReactiveSwift may now look cleaner, without the clutter of compiler-generated reabstraction thunks. See #799 for an example.

    Source code(tar.gz)
    Source code(zip)
  • 6.7.0-rc1(Jul 23, 2021)

  • 6.6.1(Jun 23, 2021)

    Changes

    1. Updated Carthage xcconfig dependency to 1.1 for proper building arm64 macOS variants. (#826, kudos to @MikeChugunov)

    2. Fixed issue with SignalProducer.Type.interval() making Swift 5.3 a requirement. (#823 kudos to @mluisbrown)

    Source code(tar.gz)
    Source code(zip)
  • 6.6.0(Mar 8, 2021)

    This is the sixth minor release of ReactiveSwift 6.0.

    Addition

    1. Added the SignalProducer.Type.interval() operator for emitting values on a regular schedule. (#810, kudos to @mluisbrown)

    Changes

    1. When debugging your application, the call stacks involving ReactiveSwift may start to look cleaner and less cryptic. This is an on-going refactoring effort to improve the developer experience. See #799 for an example.

    2. Bumped deployment target to iOS 9.0, per Xcode 12 warnings. (#818, kudos to @harleyjcooper)

    3. Fixed a few deprecation warning when the project is being built. (#819, kudos to @apps4everyone)

    Source code(tar.gz)
    Source code(zip)
  • 6.5.0(Oct 27, 2020)

    This is the fifth minor release of ReactiveSwift 6.0.

    ⚠️ ReactiveSwift 6.5.0 is a strongly recommended update, especially for users routinely lifting custom Signal operators to work with SignalProducer.

    Changes

    1. Fixed a SignalProducer.lift issue which may leak intermediate signals. (#808)

    2. Add ExpressibleByNilLiteral constraint to OptionalProtocol (#805, kudos to @nkristek)

    3. Add variadic sugar for boolean static methods such as Property.any(boolProperty1, boolProperty2, boolProperty3) (#801, kudos to @fortmarek)

    Source code(tar.gz)
    Source code(zip)
  • 6.4.0(Sep 29, 2020)

    This is the forth minor release of ReactiveSwift 6.

    Changes

    1. Minimum deployment target is now iOS 9.0+ when using Swift Package Manager, so as to silence Xcode 12 warnings. (#802)

    2. Fix a debug assertion in Lock.try() that could be raised in earlier OS versions (< iOS 10.0, < macOS 10.12). (#747, #788)

      Specifically, ReactiveSwift now recognizes EDEADLK as expected error code from pthread_mutex_trylock alongside 0, EBUSY and EAGAIN.

    Source code(tar.gz)
    Source code(zip)
  • 6.3.0(May 25, 2020)

    This is the third minor release of ReactiveSwift 6.

    Additions

    1. Property and MutableProperty can now be used as property wrapper. Note that they remain a reference type container, so it may not be appropriate to use them in types requiring value semantics. (#781)

      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 }
        }
      }
      
    2. When combineLatest or zip over a sequence of SignalProducers or Propertys, you can now specify an optional emptySentinel parameter, which would be used when the sequence is empty.

      This becomes relevant, when the sequence of producers is calculated from some other Signal and the signal resulting from the joined producers is observed. If no value is sent when the sequence is empty, the observer gets terminated silently, and, e.g., the UI would not be updated.

      (#774, kudos to @rocketnik)

    Miscellaneous

    1. Test dependencies should no longer be built for SwiftPM users, as a result of ReactiveSwift moving to swft-tools-version: 5.2. (#784)
    Source code(tar.gz)
    Source code(zip)
  • 6.2.1(Feb 28, 2020)

    This is a patch release of ReactiveSwift 6.2.

    Changes

    • Improved performance of aggregating a sequence of Signal and SignalProducer using the static combineLatest and zip operators. (#773, kudos to @rocketnik)

    • Fixed the SignalProducer.debounce operator which does not deliver any value if having been started more than once. (#772, kudos to @gpambrozio)

    Source code(tar.gz)
    Source code(zip)
  • 6.2.0(Jan 7, 2020)

    Changes

    1. FlattenStrategy.throttle is introduced. (#713, kudos to @inamiy)

      Given a first inner stream, all subsequent inner streams sent by the upstream would be dropped until the first inner stream has completed. The whole process repeats indefinitely until the upstream terminates. The behavior is akin to throttle(_:on:) except for operating in the domain of streams instead of time.

    2. The package file of ReactiveSwift now declares supported platforms. (#761, kudos to @ikesyo)

    3. Renamed filterMap to compactMap and deprecated filterMap (#746, kudos to @Marcocanc)

    Source code(tar.gz)
    Source code(zip)
  • 6.1.0(Jun 20, 2019)

    1. Support Swift 5.1 and Xcode 11 (#739, thanks @NachoSoto!)

    2. Add all and any operators with array of arguments (#735, kudos to @olejnjak)

      let property = Property.any([boolProperty1, boolProperty2, boolProperty3])
      
    3. Fixed Result extensions ambiguity (#733, kudos to @nekrich)

    4. Add <~ binding operator to Signal.Observer (#635, kudos to @Marcocanc)

    Source code(tar.gz)
    Source code(zip)
  • 6.0.0(Apr 11, 2019)

    This release drops support for Swift 4.2 (Xcode 10/10.1) and removes the dependency on antitypical/Result. 🎉 (#702, kudos to @NachoSoto and @mdiep)

    Upgrade to 6.0.0

    • If you have used Result only as dependency of ReactiveSwift, remove all instances of import Result, import enum Result.NoError or import struct Result.AnyError and remove the Result Framework from your project.
    • Replace all cases where NoError was used in a Signal or SignalProducer with Never
    • Replace all cases where AnyError was used in a Signal or SignalProducer with Swift.Error
    Source code(tar.gz)
    Source code(zip)
  • 5.0.1(Mar 31, 2019)

  • 5.0.0(Mar 14, 2019)

    This is the first release of ReactiveSwift 5.0. It requires Swift 4.2 or above.

    Xcode 10.2 Support

    1. Swift 5.0 and Xcode 10.2 support (#707 and #711, kudos to @ChristopherRogers and @ikesyo)

    Operators

    1. New operator materializeResults and dematerializeResults (#679, kudos to @ra1028)

    Miscellaneous

    1. New convenience initializer for Action that takes a ValidatingProperty as its state (#637, kudos to @Marcocanc)
    Source code(tar.gz)
    Source code(zip)
  • 4.0.0(Jul 17, 2018)

    This is the first release of ReactiveSwift 4.0. It requires Swift 4.1 or above.

    Xcode 10 Support

    1. Swift 4.2 and Xcode 10 support (#644, kudos to @ikesyo)

    Operators

    1. New method collect(every:on:skipEmpty:discardWhenCompleted:) which delivers all values that occurred during a time interval (#619, kudos to @Qata)
    2. debounce now offers an opt-in behaviour to preserve the pending value when the signal or producer completes. You may enable it by specifying discardWhenCompleted as false (#287, kudos to @Qata)
    3. New property operator: filter (#586, kudos to @iv-mexx)
    4. New operator merge(with:) (#600, kudos to @ra1028)
    5. New operator map(value:) (#601, kudos to @ra1028)
    6. SignalProducer.merge(with:), SignalProducer.concat, SignalProducer.prefix, SignalProducer.then, SignalProducer.and, SignalProducer.or, SignalProducer.zip(with:), SignalProducer.sample(with:), SignalProducer.sample(on:), SignalProducer.take(until:), SignalProducer.take(untilReplacement:), SignalProducer.skip(until:), SignalProducer.flatMap, SignalProducer.flatMapError, SignalProducer.combineLatest(with:), Signal.flatMap, Signal.flatMapError, Signal.withLatest(from:) and Property.init(initial:then:) now accept SignalProducerConvertible conforming types (#610, #611, kudos to @ra1028)

    Changes: <~ Bindings

    1. <~ bindings now works with optional left-hand-side operands. (#642, kudos to @andersio and @Ankit-Aggarwal)

      let nilTarget: BindingTarget<Int>? = nil
      
      // This is now a valid binding. Previously required manual
      // unwrapping in ReactiveSwift 3.x.
      nilTarget <~ notifications.map { $0.count }
      

    Changes: Conditional Conformance

    1. For Swift 4.1 and above, BindingSource conformances are required to have Error parameterized as exactly NoError. As a result, Signal and SignalProducer are now conditionally BindingSource. (#590, kudos to @NachoSoto and @andersio)
    2. For Swift 4.1 and above, Signal.Event and ActionError are now conditionally Equatable. (#590, kudos to @NachoSoto and @andersio)

    Interoperability

    1. Result now interoperates with SignalProducer n-ary operators as a constant producer (#606, kudos to @Qata)

    Miscellaneous

    1. When unfair locks from libplatform are unavailable, ReactiveSwift now fallbacks to error checking Pthread mutexes instead of the default. Mitigations regarding issues with pthread_mutex_trylock have also been applied. (#654, kudos to @andersio)
    2. Lifetime may now be manually ended using Lifetime.Token.dispose(), in addition to the existing when-token-deinitializes semantic. (#641, kudos to @andersio)
    3. Bag may now be initialised with a sequence of elements. (#609, kudos to @ra1028)
    4. Non-class types may now conform to ReactiveExtensionProvider. (#636, kudos to @ra1028)
    5. Fix some documentation errors about Carthage usage (#655)
    6. [CocoaPods] CocoaPods 1.4.0 is the minimum required version. (#651, kudos to @ikesyo)
    Source code(tar.gz)
    Source code(zip)
  • 4.0.0-rc.2(Jun 14, 2018)

    This is the second release candidate of ReactiveSwift 4.0. It requires Swift 4.1 or above.

    Change

    1. Swift 4.2 and Xcode 10 support (#644, kudos to @ikesyo)
    Source code(tar.gz)
    Source code(zip)
  • 4.0.0-rc.1(Jun 1, 2018)

    This is the first release candidate of ReactiveSwift 4.0. It requires Swift 4.1.

    Operators

    1. New method collect(every:on:skipEmpty:discardWhenCompleted:) which delivers all values that occurred during a time interval (#619, kudos to @Qata)
    2. debounce now offers an opt-in behaviour to preserve the pending value when the signal or producer completes. You may enable it by specifying discardWhenCompleted as false (#287, kudos to @Qata)
    3. New property operator: filter (#586, kudos to @iv-mexx)
    4. New operator merge(with:) (#600, kudos to @ra1028)
    5. New operator map(value:) (#601, kudos to @ra1028)
    6. SignalProducer.merge(with:), SignalProducer.concat, SignalProducer.prefix, SignalProducer.then, SignalProducer.and, SignalProducer.or, SignalProducer.zip(with:), SignalProducer.sample(with:), SignalProducer.sample(on:), SignalProducer.take(until:), SignalProducer.take(untilReplacement:), SignalProducer.skip(until:), SignalProducer.flatMap, SignalProducer.flatMapError, SignalProducer.combineLatest(with:), Signal.flatMap, Signal.flatMapError, Signal.withLatest(from:) and Property.init(initial:then:) now accept SignalProducerConvertible conforming types (#610, #611, kudos to @1028)

    Changes: Conditional Conformance

    1. For Swift 4.1 and above, BindingSource conformances are required to have Error parameterized as exactly NoError. As a result, Signal and SignalProducer are now conditionally BindingSource. (#590, kudos to @NachoSoto and @andersio)
    2. For Swift 4.1 and above, Signal.Event and ActionError are now conditionally Equatable. (#590, kudos to @NachoSoto and @andersio)

    Interoperability

    1. Result now interoperates with SignalProducer n-ary operators as a constant producer (#606, kudos to @Qata)

    Miscellaneous

    1. Lifetime may now be manually ended using Lifetime.Token.dispose(), in addition to the existing when-token-deinitializes semantic. (#641, kudos to @andersio)
    2. Bag may now be initialised with a sequence of elements. (#609, kudos to @ra1028)
    3. Non-class types may now conform to ReactiveExtensionProvider. (#636, kudos to @ra1028)
    Source code(tar.gz)
    Source code(zip)
  • 3.1.0(Jan 11, 2018)

    This is the first release of ReactiveSwift 3.1. It supports Swift 3.2 and Swift 4.0.

    Bugfix

    1. Fixed a scenario of downstream interruptions being dropped. (#577, kudos to @andersio)

      Manual interruption of time shifted producers, including delay, observe(on:), throttle, debounce and lazyMap, should discard outstanding events at best effort ASAP.

      But in ReactiveSwift 2.0 to 3.0, the manual interruption is ignored if the upstream producer has terminated. For example:

      // Completed upstream + `delay`.
      SignalProducer.empty
          .delay(10.0, on: QueueScheduler.main)
          .startWithCompleted { print("The producer should have been interrupted!") }
          .dispose()
      
      // Console(t+10): The producer should have been interrupted!
      

      The expected behavior has now been restored.

      Please note that, since ReactiveSwift 2.0, while the interruption is handled immediately, the interrupted event delivery is not synchronous — it generally respects the closest asynchronous operator applied, and delivers on that scheduler.

    2. Fixed schedule(after:interval:leeway:) being cancelled when the returned Disposable is not retained. (#584, kudos to @jjoelson)

      The issue affects only direct use of QueueScheduler. SignalProducer.timer is not affected.

    Addition

    1. SignalProducer.concat now has an overload that accepts an error. (#564, kudos to @nmccann)

    Change

    1. Fix some documentation errors (#560, kudos to @ikesyo)
    Source code(tar.gz)
    Source code(zip)
  • 3.1.0-rc.1(Dec 22, 2017)

    This is the first release candidate of ReactiveSwift 3.1. It supports Swift 3.2 and Swift 4.0.

    Bugfix

    1. Fixed a scenario of downstream interruptions being dropped. (#577, kudos to @andersio)

      Manual interruption of time shifted producers, including delay, observe(on:), throttle, debounce and lazyMap, should discard outstanding events at best effort ASAP.

      But in ReactiveSwift 2.0 to 3.0, the manual interruption is ignored if the upstream producer has terminated. For example:

      // 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!
      

      The expected behavior has now been restored.

      Please note that, since ReactiveSwift 2.0, while the interruption is handled immediately, the interrupted event delivery is not synchronous — it generally respects the closest asynchronous operator applied, and delivers on that scheduler.

    Addition

    1. SignalProducer.concat now has an overload that accepts an error. (#564, kudos to @nmccann)

    Change

    1. Fix some documentation errors (#560, kudos to @ikesyo)
    Source code(tar.gz)
    Source code(zip)
  • 3.0.0(Nov 17, 2017)

    This is the first release of ReactiveSwift 3.0. It supports Swift 3.2 and Swift 4.0, and requires either Xcode 9 or the Swift 4.0 OSS compiler toolchain.

    Breaking Change

    1. Signal now uses Lifetime for resource management. (#404, kudos to @andersio)

      The Signal initialzer now accepts a generator closure that is passed with the input Observer and the Lifetime as its arguments. The original variant accepting a single-argument generator closure is now obselete. This is a source breaking change.

      // New: Add `Disposable`s to the `Lifetime`.
      let candies = Signal<U, E> { (observer: Signal<U, E>.Observer, lifetime: Lifetime) in
         lifetime += trickOrTreat.observe(observer)
      }
      
      // Obsolete: Returning a `Disposable`.
      let candies = Signal { (observer: Signal<U, E>.Observer) -> Disposable? in
         return trickOrTreat.observe(observer)
      }
      
    2. Unavailable symbols in ReactiveSwift 2.x have been removed. (#551, kudos to @ikesyo)

    Bugfix

    1. Workaround an unexpected EGAGIN error being returned by pthread in 32-bit ARM debug builds. (#508)

    2. Fixed a potential integer overflow regarding the leeway computation in SignalProducer.timer. (#506, kudos to @soxjke)

    Changes

    1. ReactiveSwift has been migrated to Swift 4.0. (#422, kudos to @andersio)

    2. SignalProducer.startWithSignal now returns the value of the setup closure. (#533, kudos to @Burgestrand)

    3. Disabled code coverage data to allow app submissions with Xcode 9.0 (see https://github.com/Carthage/Carthage/issues/2056, kudos to @NachoSoto)

    4. The SignalProducer internals have undergone a significant refactoring, which bootstraps the effort to reduce the overhead of constant producers and producer compositions. (#487, kudos to @andersio)

    Deprecation

    1. Signal.Observer.action has been deprecated. Use Signal.Observer.send instead. (#515)
    Source code(tar.gz)
    Source code(zip)
  • 3.0.0-rc.1(Oct 30, 2017)

    This is the first release candidate of ReactiveSwift 3.0. It supports both Swift 3.2 and Swift 4.0.

    Bugfix

    1. Fixed a potential integer overflow regarding the leeway computation in SignalProducer.timer. (#506, kudos to @soxjke)
    Source code(tar.gz)
    Source code(zip)
  • 3.0.0-alpha.1(Oct 19, 2017)

    This is the first alpha release of ReactiveSwift 3.0. It supports Swift 3.2 and Swift 4.0, and requires either Xcode 9 or the Swift 4.0 OSS compiler toolchain.

    Breaking Change

    1. Signal now uses Lifetime for resource management. (#404, kudos to @andersio)

      The Signal initialzer now accepts a generator closure that is passed with the input Observer and the Lifetime as its arguments. The original variant accepting a single-argument generator closure is now obselete. This is a source breaking change.

      // New: Add `Disposable`s to the `Lifetime`.
      let candies = Signal<U, E> { (observer: Signal<U, E>.Observer, lifetime: Lifetime) in
         lifetime += trickOrTreat.observe(observer)
      }
      
      // Obsolete: Returning a `Disposable`.
      let candies = Signal { (observer: Signal<U, E>.Observer) -> Disposable? in
         return trickOrTreat.observe(observer)
      }
      

    Bugfix

    1. Workaround an unexpected EGAGIN error being returned by pthread in 32-bit ARM debug builds. (#508)

    Changes

    1. ReactiveSwift has been migrated to Swift 4.0. (#422, kudos to @andersio)

    2. SignalProducer.startWithSignal now returns the value of the setup closure. (#533, kudos to @Burgestrand)

    3. Disabled code coverage data to allow app submissions with Xcode 9.0 (see https://github.com/Carthage/Carthage/issues/2056, kudos to @NachoSoto)

    4. The SignalProducer internals have undergone a significant refactoring, which bootstraps the effort to reduce the overhead of constant producers and producer compositions. (#487, kudos to @andersio)

    Deprecation

    1. Signal.Observer.action has been deprecated. Use Signal.Observer.send instead. (#515)
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0-alpha.2(Sep 16, 2017)

    This is the second alpha release of ReactiveSwift 2.1. It targets Swift 3.1, Swift 3.2 and Swift 4.0.

    Changes

    1. Disabled code coverage data to allow app submissions with Xcode 9.0 (see https://github.com/Carthage/Carthage/issues/2056, kudos to @NachoSoto)
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0-alpha.1(Sep 15, 2017)

    This is the first alpha release of ReactiveSwift 2.1. It targets Swift 3.1, Swift 3.2 and Swift 4.0.

    Changes

    1. Signal.Observer.action has been deprecated. Use Signal.Observer.send instead. (#515)

    2. Workaround an unexpected EGAGIN error being returned by pthread in 32-bit ARM debug builds. (#508)

    3. The SignalProducer internals have undergone a significant refactoring, which bootstraps the effort to reduce the overhead of constant producers and producer compositions. (#487, kudos to @andersio)

    Source code(tar.gz)
    Source code(zip)
  • 2.0.1(Aug 16, 2017)

    This is the first maintenance release of ReactiveSwift 2.0. It targets Swift 3.1 with preliminary support of Swift 3.2 and Swift 4.0.

    Change

    1. Addressed the exceptionally high build time. (#495)

    Addition

    1. New operator retry(upTo:interval:on:). (#496, kudos to @tjnet)

      This delays retrying on failure by interval until hitting the upTo limitation.

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Jul 21, 2017)

    This is the second major release of ReactiveSwift. It requires Swift 3.1 (Xcode 8.3.x), and preliminarily supports Swift 3.2 and Swift 4.0 (Xcode 9).

    Highlights

    Safer Signal lifetime semantics (#355, #463)

    The Signal lifetime semantics have been updated to improve interoperability with memory debugging tools. ReactiveSwift 2.0 adopted a new Signal internal which does not exploit deliberate retain cycles that consequentially confuse memory debugging tools.

    ReactiveSwift 2.0 automatically terminates a Signal, when:

    1. (New) its input observer of the Signal is not retained; OR
    2. the Signal is neither retained nor has any active observer;

    Input observer refers to the Observer the Signal receives input from. It is created and passed to you by Signal.init, Signal.pipe and SignalProducer.init.

    Specifically, when an input Observer deinitializes, semantically it implies the associated Signal has no further event to be delivered. So ReactiveSwift would now interrupt the Signal automatically, and release all the associated resources.

    func scopedSignal() -> Signal<Never, NoError> {
        // Note that the `Observer` is discarded immediately.
        let (signal, _) = Signal<Never, NoError>.pipe()
        return signal
    }
    
    var isInterrupted = false
    
    withExtendedLifetime(scopedSignal()) { signal in
        signal.observeInterrupted { isInterrupted = true }
    
        // ReactiveSwift 1.x:
        // The `Signal` is still alive, probably forever unless the observer is detached.
        expect(isInterrupted) == false
    
        // ReactiveSwift 2.0:
        // The `Signal` is automatically interrupted, since the deinitialization of the
        // input `Observer` implies no further event would be sent.
        expect(isInterrupted) == true
    }
    

    Similarly for a deinitialised Signal, since no further observation can ever be made, ReactiveSwift would dispose of it when it knows for certain it has no active observer. Note that this is already the case for ReactiveSwift 1.x.

    let checkpoint = AnyDisposable()
    let escaped = CompositeDisposable()
    
    func scopedObserver() -> Signal<Never, NoError>.Observer {
        // Note that the `Signal` does not escape the scope.
        let (signal, observer) = Signal<Never, NoError>.pipe(disposable: checkpoint)
        escaped += signal.observe(Observer())
        return observer
    }
    
    withExtendedLifetime(scopedObserver()) {
        escaped.dispose()
    
        // ReactiveSwift 1.x and 2.0:
        // Since no further observation can be made to the `Signal`, and it has no
        // active observer at this point, the `Signal` is automatically disposed of.
        expect(checkpoint.isDisposed) == true
    }
    

    In short, the Signal terminates when either of its ends implicitly declare their lack of interest — derived from the deinitialization of the Signal or the input Observer — to send or receive events. This makes ReactiveSwift more ARC friendly than before.

    It is expected that memory debugging tools would no longer report irrelevant negative leaks that were once caused by the ReactiveSwift internals.

    SignalProducer resource management (#334)

    SignalProducer now uses Lifetime for resource management. You may observe the Lifetime for the disposal of the produced Signal. You may also continue to use the += convenience on Lifetime for adding Disposables.

    let producer = SignalProducer<Int, NoError> { observer, lifetime in
        lifetime += numbers.observe(observer)
    }
    

    If you need to interrupt the SignalProducer, you should now do it through the input Observer:

    let producer = SignalProducer<Int, NoError> { observer, _ in
        observer.sendInterrupted()
    }
    

    Reduced overhead for all SignalProducer lifted operators. (#140)

    All SignalProducer lifted operators no longer yield an extra Signal. As a result, the cost of event delivery has been considerably reduced, and SignalProducer is generally as performant as Signal.

    N-ary SignalProducer operators with generic operands (#410)

    N-ary SignalProducer operators are now generic and accept any type that can be expressed as SignalProducer. Types may conform to SignalProducerConvertible to become an eligible operand.

    For example:

    let property = MutableProperty<Int>(0)
    let producer = SignalProducer<Int, NoError>.never
    let signal = Signal<Int, NoError>.never
    
    /// Valid in ReactiveSwift 2.0.
    _ = SignalProducer.combineLatest(property, producer, signal)
    

    Changes

    Signal and SignalProducer

    1. All Signal and SignalProducer operators now belongs to the respective concrete types. (#304)

      Custom operators should extend the concrete types directly. SignalProtocol and SignalProducerProtocol should be used only for constraining associated types.

    2. combineLatest and zip are optimised to have a constant overhead regardless of arity, mitigating the possibility of stack overflow. (#345, #471, kudos to @stevebrambilla for catching a bug in the implementation)

    3. When composing Signal and SignalProducer of inhabitable types, e.g. Never or NoError, ReactiveSwift now warns about operators that are illogical to use, and traps at runtime when such operators attempt to instantiate an instance. (#429, kudos to @andersio)

    4. interrupted now respects observe(on:). (#140)

      When a SignalProducer is interrupted, if observe(on:) is the last applied operator, interrupted would now be delivered on the Scheduler passed to observe(on:) just like other events.

    5. flatMap(_:transform:) is renamed to flatMap(_:_:). (#339)

    6. promoteErrors(_:)is renamed to promoteError(_:). (#408)

    7. Event is renamed to Signal.Event. (#376)

    8. Observer is renamed to Signal.Observer. (#376)

    Action

    1. Action(input:_:), Action(_:), Action(enabledIf:_:) and Action(state:enabledIf:_:) are renamed to Action(state:execute:), Action(execute:), Action(enabledIf:execute:) and Action(state:enabledIf:execute:) respectively. (#325)

    2. Feedbacks from isEnabled and isExecuting to the state of the same Action, including all enabledIf convenience initializers, no longer deadlocks. (#400, kudos to @andersio)

      Note that legitimate feedback loops would still deadlock.

    3. Added new convenience initialisers to Action that make creating actions with state input properties easier. When creating an Action that is conditionally enabled based on an optional property, use the renamed Action.init(unwrapping:execute:) initialisers. (#455, kudos to @sharplet)

    Properties

    1. The memory overhead of property composition has been considerably reduced. (#340)

    2. MutableProperty now enforces exclusivity of access. (#419, kudos to @andersio)

      In other words, nested modification in MutableProperty.modify is now prohibited. Generally speaking, it should have extremely limited impact as in most cases the MutableProperty would have been deadlocked already.

    3. ValidationResult and ValidatorOutput have been renamed to ValidatingProperty.Result and ValidatingProperty.Decision, respectively. (#443)

    Bindings

    1. The BindingSource now requires only a producer representation of self. (#359)

    2. The <~ operator overloads are now provided by BindingTargetProvider. (#359)

    Disposables

    1. SimpleDisposable and ActionDisposable has been folded into AnyDisposable. (#412)

    2. CompositeDisposable.DisposableHandle is replaced by Disposable?. (#363)

    3. The += operator overloads for CompositeDisposable are now hosted inside the concrete types. (#412)

    Bag

    1. Improved the performance of Bag. (#354)

    2. RemovalToken is renamed to Bag.Token. (#354)

    Schedulers

    1. Scheduler gains a class bound. (#333)

    Lifetime

    1. Lifetime.ended now uses the inhabitable Never as its value type. (#392)

    Atomic

    1. Signal and Atomic now use os_unfair_lock when it is available. (#342)

    Additions

    1. FlattenStrategy.race is introduced. (#233, kudos to @inamiy)

      race flattens whichever inner signal that first sends an event, and ignores the rest.

    2. FlattenStrategy.concurrent is introduced. (#298, kudos to @andersio)

      concurrent starts and flattens inner signals according to the specified concurrency limit. If an inner signal is received after the limit is reached, it would be queued and drained later as the in-flight inner signals terminate.

    3. New operators: reduce(into:) and scan(into:). (#365, kudos to @ikesyo)

      These variants pass to the closure an inout reference to the accumulator, which helps the performance when a large value type is used, e.g. collection.

    4. combinePrevious for Signal and SignalProducer no longer requires an initial value. The first tuple would be emitted as soon as the second value is received by the operator if no initial value is given. (#445, kudos to @andersio)

    5. New operator: promoteValue. (#429)

    6. promoteError can now infer the new error type from the context. (#413, kudos to @andersio)

    7. Property(initial:then:) gains overloads that accept a producer or signal of the wrapped value type when the value type is an Optional. (#396)

    Swift 3.2+

    1. In Swift 3.2 or later, you can use map() with the new Smart Key Paths. (#435, kudos to @sharplet)

    2. In Swift 3.2 or later, you may create BindingTarget for a key path of a specific object. (#440, kudos to @andersio)

    Deprecations and Removals

    1. The requirement BindingSource.observe(_:during:) and the implementations have been removed.

    2. All Swift 2 (ReactiveCocoa 4) obsolete symbols have been removed.

    3. All deprecated methods and protocols in ReactiveSwift 1.1.x are no longer available.

    Bugfixes

    1. Fixed an impedance mismatch in the Signal internals that caused heap corruptions. (#449, kudos to @gparker42)

    2. Mitigated a race condition related to ARC in the Signal internal. (#456, kudos to @andersio)

    Acknowledgement

    Thank you to all of @ReactiveCocoa and all our contributors, but especially to @andersio, @calebd, @cwalcott, @eimantas, @erwald, @gparker42, @ikesyo, @Igor-Palaguta, @inamiy, @keitaito, @Marcocanc, @mdiep, @NachoSoto, @sharplet, @stephencelis, @stevebrambilla and @tjnet. ReactiveSwift is only possible due to the many hours of work that these individuals have volunteered. ❤️

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-rc.3(Jul 12, 2017)

    This is the third release candidate of ReactiveSwift 2.0. It targets Swift 3.1 with preliminary support of Swift 3.2 and Swift 4.0.

    Changes

    1. Updated for Swift 4.0 shipped with Xcode 9 beta 3. (#484, kudos to @stephencelis)

    2. Lifetime.+= which ties a Disposable to a Lifetime, is now part of the public API and is no longer deprecated.

    3. Feedbacks from isEnabled to the state of the same Action no longer deadlocks if it does not constitute an infinite feedback loop. (#481, kudos to @andersio)

      Note that isExecuting already supports Action state feedback, and legitimate feedback loops would still deadlock.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.5(Jul 12, 2017)

    This is a maintenance release of ReactiveSwift 1.1. It is compatible with Swift 3.

    Fixed

    • A compile error with Xcode 9Ăź3 (#484, thanks @stephencelis!)
    Source code(tar.gz)
    Source code(zip)
  • 1.1.4(Jul 12, 2017)

Owner
A framework for composing and transforming streams of values
null
The easiest way to observe values in Swift.

Observable is the easiest way to observe values in Swift. How to Create an Observable and MutableObservable Using MutableObservable you can create and

Robert-Hein Hooijmans 368 Nov 9, 2022
An experimental time traveling state store for SwiftUI

SwiftUI Time Travel A SwiftUI state store and view that allow you to scrub through an application's state. This is a super rough prototype: it's only

Tim Donnelly 139 Sep 14, 2022
Radio Streams from all over the world. Free and Open.

RadioBrowserKit - The Swift SDK for Radio Browser Radio Streams from all over the world. Free and Open. RadioBrowserKit is a Swift package which lets

Frank Gregor 5 Oct 17, 2022
Open source implementation of Apple's Combine framework for processing values over time.

OpenCombine Open-source implementation of Apple's Combine framework for processing values over time. The main goal of this project is to provide a com

OpenCombine 2.4k Dec 26, 2022
Open source implementation of Apple's Combine framework for processing values over time.

OpenCombine Open-source implementation of Apple's Combine framework for processing values over time. The main goal of this project is to provide a com

OpenCombine 2.4k Jan 2, 2023
Open-source implementation of Apple's Combine for processing values over time

CombineX 简体中文 Open-source implementation of Apple's Combine for processing values over time. Though CombineX have implemented all the Combine interfac

Luo Xiu 1 Dec 30, 2021
Evented I/O streams for Swift

Noze.io "Das Haus das VerrĂĽckte macht." Noze.io is an attempt to carry over the Node.js ideas into pure Swift. It uses libdispatch for event-driven, n

The Noze Consortium 305 Oct 14, 2022
Evented I/O streams for Swift

Noze.io "Das Haus das VerrĂĽckte macht." Noze.io is an attempt to carry over the Node.js ideas into pure Swift. It uses libdispatch for event-driven, n

The Noze Consortium 305 Oct 14, 2022
Lazy streams in Swift.

Stream This is a Swift microframework providing a lazy Stream<T> type with generic implementations of ==/!= where T: Equatable. Streams are lazily-pop

Antitypical 82 Jan 29, 2022
Time is a Swift package that makes dealing with calendar values a natural and straight-forward process.

Time Time is a Swift package that makes dealing with calendar values a natural and straight-forward process. Working with calendars can be extremely c

Dave DeLong 2k Dec 31, 2022
AnylineFaceAuthentication pairs identity document scanning with a real-time liveness check utilizing the iPhone's camera, best suited for authenticating users over the internet.

AnylineFaceAuthentication AnylineFaceAuthentication pairs identity document scanning with a real-time liveness check utilizing the iPhone's camera, be

null 0 Mar 7, 2022
PublisherKit - An open source implementation of Apple's Combine framework for processing asynchronous events over time

Publisher Kit Overview PublisherKit provides a declarative Swift API for processing asynchronous events over time. It is an open source version of App

null 5 Feb 22, 2022
A "time ago", "time since", "relative date", or "fuzzy date" category for NSDate and iOS, Objective-C, Cocoa Touch, iPhone, iPad

Migration 2014.04.12 NSDate+TimeAgo has merged with DateTools. DateTools is the parent project and Matthew York is the project head. This project is n

Kevin Lawler 1.8k Dec 2, 2022
Stopwatch is a Swift App that measures amount of time elapsed from a particular time.

Stopwatch Stopwatch is a Swift App that measures amount of time elapsed from a particular time. It highly mocks the stopwatch of Apple's offical App c

Kushal Shingote 3 Feb 20, 2022
A replacement for as which runs in constant time instead of O(n) when the conformance is not satisfiedA replacement for as which runs in constant time instead of O(n) when the conformance is not satisfied

ZConform A replacement for as? which runs in constant time instead of O(n) when the conformance is not satisfied. How it works ZConform does a one-tim

Emerge Tools 20 Aug 4, 2022
Sync your app's time with server's UTC time

ServerSync for iOS Apps Sometimes your app can't rely on the device's date and time settings being correct. This library will help you calibrate your

null 10 Dec 16, 2021
Type-safe CAAnimation wrapper. It makes preventing to set wrong type values.

TheAnimation TheAnimation is Type-safe CAAnimation wrapper. Introduction For example, if you want to animate backgroundColor with CABasicAnimation, yo

Taiki Suzuki 222 Dec 6, 2022
HexColor is a simple extension that lets you initialize UIColors the way they were meant to be initialized: With hex integer values

HexColor is a simple extension that lets you initialize UIColors the way they were meant to be initialized: With hex integer values. Requirem

Tuomas Artman 103 Nov 24, 2022
Observable is the easiest way to observe values in Swift.

Observable is the easiest way to observe values in Swift. How to Create an Observable and MutableObservable Using MutableObservable you can create and

Robert-Hein Hooijmans 368 Nov 9, 2022
UISlider clone with multiple thumbs and values, range highlight, optional snap intervals, optional value labels, either vertical or horizontal.

MultiSlider UISlider clone with multiple thumbs and values, range highlight, optional snap intervals, optional value labels, either vertical or horizo

Yonat Sharon 326 Dec 29, 2022