A Swift framework for reactive programming.

Overview

CwlSignal

An implementation of reactive programming. For details, see the article on Cocoa with Love, CwlSignal, a library for reactive programming.

NOTE: the CwlSignal.playground mentioned in the article is currently absent from the repository. A complication around putting playgrounds inside packages needs to be resolved, then it will be restored.

Adding to your project

The CwlSignal library requires the Swift Package Manager. Minimum requirements are iOS 8 or macOS 10.10 and Swift 5.0.

Add the following to the dependencies array in your "Package.swift" file:

.package(url: "https://github.com/mattgallagher/CwlSignal.git", from: Version(3, 0, 0)),

NOTE: even though this git repository includes its dependencies in the Dependencies folder, building via the Swift Package manager fetches and builds these dependencies independently.

CocoaPods and Carthage

Up to version 2.2.0, this library supported CocoaPods and Carthage. If you wish to use these package managers, you can check out the CwlSignal 2.2.0 tag.

Comments
  • Installation through Carthage fails citing Bitcode issues

    Installation through Carthage fails citing Bitcode issues

    Trying to install 2.0.0-beta.8 through Carthage with Xcode 8.3.3:

    ld: bitcode bundle could not be generated because '/Users/zoul/Library/Caches/org.carthage.CarthageKit/DerivedData/CwlSignal/2.0.0-beta.8/Build/Products/Release-iphoneos/CwlUtils.framework/CwlUtils' was built without full bitcode. All frameworks and dylibs for bitcode must be generated from Xcode Archive or Install build for architecture arm64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    

    Am I doing something wrong? I tried 1.x, but that also fails to install through Carthage for a different reason.

    opened by zoul 6
  • Add podspec

    Add podspec

    Following from #2

    I've made the following assumptions:

    • the license is ISC
    • platform deployment targets in the Xcode project are correctly minimum
    • the 'homepage' listed on CocoaPods.org/CLI search results is preferred to be this repo, not the blog post.
    • tvOS and watchOS are not supported. If they are, something like the following can be added:
      s.watchos.deployment_target = "3.0"
      s.tvos.deployment_target = "10.0"
    

    After merging this you will need to push to trunk. If you want I can do this, including yourself as a full-rights contributor on the trunk service, ownership can be transferred at any time.

    opened by Ashton-W 6
  • Carthage Support

    Carthage Support

    Pleased to say CwlSignal supports Carthage already.

    However, it generates the following binaries:

    Carthage/
    └── Build
        ├── Mac
        │   ├── CwlCatchException.framework
        │   ├── CwlCatchException.framework.dSYM
        │   ├── CwlPreconditionTesting.framework
        │   ├── CwlPreconditionTesting.framework.dSYM
        │   ├── CwlSignal.framework
        │   ├── CwlSignal.framework.dSYM
        │   ├── CwlUtils.framework
        │   └── CwlUtils.framework.dSYM
        ├── iOS
        │   ├── CwlCatchException.framework
        │   ├── CwlCatchException.framework.dSYM
        │   ├── CwlPreconditionTesting.framework
        │   ├── CwlPreconditionTesting.framework.dSYM
        │   ├── CwlSignal.framework
        │   ├── CwlSignal.framework.dSYM
        │   ├── CwlUtils.framework
        │   └── CwlUtils.framework.dSYM
        └── tvOS
            ├── CwlPreconditionTesting.framework
            └── CwlPreconditionTesting.framework.dSYM
    

    Unfortunately Carthage will build the schemes in all projects it finds, including the CwlUtils. Users of this framework only actually need CwlSignal.framework.

    We could document this fact for Carthage users. I don't know of a way to control what Cathage builds. Thoughts?

    opened by Ashton-W 6
  • [Xcode 10 beta 4] Possibly there are two concurrent builds running in the same filesystem location

    [Xcode 10 beta 4] Possibly there are two concurrent builds running in the same filesystem location

    Checked out e73f2f4 commit & tried building same project on Xcode 10 beta 1 and can't get past this:

    PhaseScriptExecution Run\ Script /Users/---/Library/Developer/Xcode/DerivedData/----gstrjbtdifdhifbzsgokqjsutevz/Build/Intermediates.noindex/CwlSignal.build/Debug-iphoneos/CwlUtils_iOS.build/Script-C9351F8C1F0B6E820038F4E0.sh (in target: CwlUtils_iOS)
        cd /Users/---/Projects/---/----Xcode10/Vendor/CwlSignal
        /bin/sh -c /Users/---/Library/Developer/Xcode/DerivedData/----gstrjbtdifdhifbzsgokqjsutevz/Build/Intermediates.noindex/CwlSignal.build/Debug-iphoneos/CwlUtils_iOS.build/Script-C9351F8C1F0B6E820038F4E0.sh
    
    Build settings from command line:
        ARCHS = arm64
        BITCODE_GENERATION_MODE = marker
        CACHE_ROOT = /var/folders/nv/2btd50sn4973rcvjddc0xp740000gn/C/com.apple.DeveloperTools/10.0-10L176w/Xcode
        DSTROOT = /tmp/CwlSignal.dst
        MODULE_CACHE_DIR = /Users/---/Library/Developer/Xcode/DerivedData/ModuleCache.noindex
        OBJROOT = /Users/---/Library/Developer/Xcode/DerivedData/----gstrjbtdifdhifbzsgokqjsutevz/Build/Intermediates.noindex
        ONLY_ACTIVE_ARCH = YES
        SDKROOT = iphoneos12.0
        SRCROOT = /Users/---/Projects/Framme/----Xcode10/Vendor/CwlSignal
        SYMROOT = /Users/---/Library/Developer/Xcode/DerivedData/----gstrjbtdifdhifbzsgokqjsutevz/Build/Products
        TOOLCHAINS = com.apple.dt.toolchain.XcodeDefault
    
    note: Using new build system
    note: Planning build
    note: Constructing build description
    Build system information
    error: unable to attach DB: error: accessing build database "/Users/---/Library/Developer/Xcode/DerivedData/Biketo-gstrjbtdifdhifbzsgokqjsutevz/Build/Intermediates.noindex/XCBuildData/build.db": database is locked Possibly there are two concurrent builds running in the same filesystem location.
    
    ** BUILD FAILED **
    
    opened by andreyz 4
  • Executing test target fails because of development team id

    Executing test target fails because of development team id

    Hi, I’m trying to execute the test target on macOS. Both Xcode 8 and 9b4 fail, it seems like your personal development team ID is hardcoded in both the local project files and the downloaded dependencies. Do the tests run for you on a vanilla machine/user account? I might be doing something wrong, though, the whole dependency download and test build chain is quite involved and too clever for me.

    No signing certificate "Mac Development" found:  No "Mac Development" signing certificate matching team ID "S7YQ892G6G" with a private key was found.
    
    opened by Soryu 4
  • Lastest commits in CwlUtils are breaking CwlSignal current version

    Lastest commits in CwlUtils are breaking CwlSignal current version

    As you did not have published CwlSignal and CwlUtils as CocoaPods public pod, people currently can only point to your github repo if they want to use CwlSignal.

    Unfortunately with direct github links you cannot specify version of the pod. Lastest changes in CwlUtils (after Oct25, 2018/2.0 tag) therefore are breaking current CwlSignal pod.

    It would be good idea to push stable releases of the CwlUtils and CwlSignal pods to CocoaPods specs repo to let people use stable builds with specified version. See: https://guides.cocoapods.org/making/getting-setup-with-trunk

    opened by xjki 3
  • Undeclared type 'Cancellable'?

    Undeclared type 'Cancellable'?

    I'm probably missing something very obvious, but when I try and install CwlSignal with Carthage, I'm getting many compilation errors (from Carthage's xcodebuild log) complaining about the use of the Cancellable type, for example:

    CwlSignal/CwlSignal.swift:1226:50: error: use of undeclared type 'Cancellable'
    public final class SignalInput<T>: SignalSender, Cancellable {
                                                     ^~~~~~~~~~~
    

    I did some digging in the CwlSignal source, and I can't actually see where that type is declared. Is there some other dependency I should make sure to include first, or something? Or am I just being dense? Any help would be most appreciated. Thanks!

    opened by stevenbedrick 3
  • Flattened signals don't propagate errors from inner signals

    Flattened signals don't propagate errors from inner signals

    Hey Matt,

    Thanks for releasing CwlSignal - it's been fun to try out over the last couple days.

    One difference I noticed between CwlSignal and ReactiveSwift is that errors from flattened inner signals aren't propagated to the outer signal. It looks like this affects flatMap* and concatMap, or maybe wherever a SignalMergeSet is used with closesOutput set to false.

    For example, I was expecting this (non-SignalError) error from the inner signal to be emitted:

    func testFlatMapPropagatesInnerSignalErrors() {
    	var results = [Result<Int>]()
    	_ = Signal.fromSequence([1, 2]).flatMap { v in
    		return Signal<Int>.generate(context: .direct) { input in
    			guard let i = input else { return }
    			switch v {
    			case 1: i.send(value: v*10)
    			case 2: i.send(error: TestError.oneValue) // Expected this error to close / terminate the signal
    			default: fatalError()
    			}
    		}
    	}.subscribe { r in
    		results.append(r)
    	}
    
    	XCTAssert(results.at(0)?.value == 10)
    	XCTAssert(results.at(1)?.error as? TestError == .oneValue) // Failed, got SignalError.closed
    }
    

    I didn't see a test covering this, so not sure if the behavior is intentional?

    The Reactive X documentation for "FlatMap" doesn't spell this out either, but I think it's standard to propagate inner errors in RxJava, etc. as well.

    opened by stevebrambilla 3
  • Deadlock

    Deadlock

    The following code deadlocks when signal2 is created:

    let context = Exec.asyncQueue()
    
    let signal1 = Signal.from(sequence: [1])
        .continuous()
    
    let signal2 = signal1
        .map(context: context) { 2*$0 }
        .continuous()
    

    queue.sync is called when already executing on queue.

    I believe this was introduced in the 2.0 refactoring.

    opened by cosmer 2
  • CwlUtils.framework is missing in Products

    CwlUtils.framework is missing in Products

    I'm including CwlSignal as a sub-project, which worked well before the xcode10 merge, since now I can't reference CwlUtils framework in the Copy to Frameworks build step.

    opened by andreyz 2
  • Add support for key paths?

    Add support for key paths?

    Key paths would make a nice addition to the API, for example on Signal:

    func filterMap<U>(_ path: KeyPath<OutputValue, U?>) -> Signal<U> {
        return filterMap { $0[keyPath: path] }
    }
    

    Hopefully we will eventually get some kind of keypath ↔︎ function equivalence on the language level, but until then, would you consider adding the overloads for key paths where appropriate?

    opened by zoul 2
  • Unable to update my source code with Xcode 12

    Unable to update my source code with Xcode 12

    Hi, I am facing issue below while trying to upgrade my app with Xcode 12.4. Please add support for Xcode 12 .

    Undefined symbols for architecture armv7: "type metadata accessor for CwlUtils.(DequeBuffer in _205C59B1D6FDABD6FAE37E9199C346A4)", referenced from: CwlSignal.Signal.(resumeIfPossibleInternal in _ACD91BA4CE4CE61201EA964A7D8CD939)(dw: inout CwlUtils.DeferredWork) -> () in CwlSignal.o CwlSignal.Signal.(pop in _ACD91BA4CE4CE61201EA964A7D8CD939)() -> Swift.Result<A, CwlSignal.SignalEnd>? in CwlSignal.o CwlSignal.Signal.(specializedSyncPop in _ACD91BA4CE4CE61201EA964A7D8CD939)() -> () in CwlSignal.o ld: symbol(s) not found for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)

    opened by abhisheksahay 0
  • Fixed linker error when building Release configuration with Xcode 12

    Fixed linker error when building Release configuration with Xcode 12

    Undefined symbols for architecture arm64: "type metadata accessor for CwlUtils.(DequeBuffer in _205C59B1D6FDABD6FAE37E9199C346A4)", referenced from: CwlSignal.Signal.send(result: Swift.Result<A, CwlSignal.SignalEnd>, predecessor: Swift.Unmanaged<Swift.AnyObject>?, activationCount: Swift.Int, activated: Swift.Bool) -> CwlSignal.SignalSendError? in CwlSignal.o CwlSignal.Signal.(specializedSyncPop in _ACD91BA4CE4CE61201EA964A7D8CD939)() -> () in CwlSignal.o CwlSignal.Signal.(resumeIfPossibleInternal in _ACD91BA4CE4CE61201EA964A7D8CD939)(dw: inout CwlUtils.DeferredWork) -> () in CwlSignal.o CwlSignal.Signal.(pop in _ACD91BA4CE4CE61201EA964A7D8CD939)() -> Swift.Result<A, CwlSignal.SignalEnd>? in CwlSignal.o

    opened by oanapopescu-garmin 0
  • iOS Version Issue

    iOS Version Issue

    Hello! The minimum iOS version specified in the project build settings is iOS 8, but the code (specifically CwlSignal.swift) calls os_unfair_lock_unlock(), which (according to the compiler) is not available in < iOS 10. Bumping the iOS deployment target up to iOS 10 fixes the issue and things compile normally. Would it be reasonable at this point to update the project to require iOS 10 at this point?

    opened by stevenbedrick 0
  • Provide benchmark code

    Provide benchmark code

    On your blog post introducing CwlSignal (emphasis added):

    CwlSignal is fast; it can deliver multiple millions of values per second synchronously (more than 4 million per second per core on my Mac) and hundreds of thousands of values per second asynchronously (more than 200 000 values per second per core on my Mac). That makes it at least as fast as prominent competitor implementations and in most cases, between 2 and 10 times faster.

    Can you provide more detail on how you arrived at this and what specific libraries you were comparing against? It would be great if others could be able to reproduce those results.

    I ran into this repo recently and the result were unexpected considering the performance claim. CwlSignal ended up coming last in all tests, in some cases significantly.

    I'm not trying to accuse you of misleading. Certainly there are going to be flaws in the way those tests are done*, but currently that's the only comparison of frp libs for ios that I could find.

    * In particular, the version of each lib used in that repo had to be updated. One of the tests had to be modified because it was unfairly iterating far more on CwlSignal than others, etc...

    opened by cfilipov 5
Owner
Matt Gallagher
Matt Gallagher
Reactive Programming in Swift

Rx is a generic abstraction of computation expressed through Observable<Element> interface, which lets you broadcast and subscribe to values and other

ReactiveX 23.1k Jan 5, 2023
A Swift Reactive Programming Kit

ReactiveKit is a lightweight Swift framework for reactive and functional reactive programming that enables you to get into the reactive world today. T

Declarative Hub 1.2k Dec 29, 2022
Swift Reactive Programming.

ReactKit Swift Reactive Programming. How to install See Wiki page. Example For UI Demo, please see ReactKit/ReactKitCatalog. Key-Value Observing // cr

ReactKit 1.2k Nov 6, 2022
Simple and lightweight Functional Reactive Coding in Swift for the rest of us

The simplest Observable<T> implementation for Functional Reactive Programming you will ever find. This library does not use the term FRP (Functional R

Jens Ravens 1.1k Jan 3, 2023
A reactive wrapper built around UIImagePickerController.

RxMediaPicker RxMediaPicker is a RxSwift wrapper built around UIImagePickerController consisting in a simple interface for common actions like picking

RxSwift Community 180 Apr 24, 2022
RxSwift reactive wrapper for view gestures

RxGesture Usage To run the example project, clone the repo, in the Example folder open RxGesture.xcworkspace. You might need to run pod install from t

RxSwift Community 1.3k Dec 30, 2022
Reactive Keyboard in iOS

RxKeyboard RxKeyboard provides a reactive way of observing keyboard frame changes. Forget about keyboard notifications. It also perfectly works with U

RxSwift Community 1.4k Dec 29, 2022
Reactive WebSockets

RxWebSocket Reactive extensions for websockets. A lightweight abstraction layer over Starscream to make it reactive. Installation RxWebSocket is avail

Flávio Caetano 57 Jul 22, 2022
A powerful, minimal and composable architecture for building reactive iOS apps with SwiftUI or UIKit

SourceArchitecture A simple yet powerful framework for reactive programming with only a minimal optimized set of types. Sources are self-contained, hi

Daniel Hall 6 Nov 1, 2022
Store-App - Store app made for IOS using Swift programming language

Store-App Store app views products, cart, and using login from https://fakestore

Anas Khalil 2 Jan 1, 2022
Aftermath is a stateless message-driven micro-framework in Swift

Aftermath is a stateless message-driven micro-framework in Swift, which is based on the concept of the unidirectional data flow architecture.

HyperRedink 70 Dec 24, 2021
An observables framework for Swift

?? snail A lightweight observables framework, also available in Kotlin Installation Carthage You can install Carthage with Homebrew using the followin

Compass 179 Nov 21, 2022
Cocoa framework and Obj-C dynamism bindings for ReactiveSwift.

Reactive extensions to Cocoa frameworks, built on top of ReactiveSwift. ⚠️ Looking for the Objective-C API? ?? Migrating from RAC 4.x? ?? Release Road

null 20k Jan 8, 2023
Two-way data binding framework for iOS. Only one API to learn.

BindKit A simple to use two-way data binding framework for iOS. Only one API to learn. Supports Objective-C, Swift 5, Xcode 10.2, iOS 8 and above. Shi

Electric Bolt 13 May 25, 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
This Repository holds learning data on Combine Framework

Combine Framework List of Topics Welcome, every section in this repo contains a collection of exercises demonstrating combine's utilization as well as

Julio Ismael Robles 2 Mar 17, 2022
Binding - Data binding framework (view model binding on MVVM) written using propertyWrapper and resultBuilder

Binding Data binding framework (view model binding on MVVM) written using @prope

Sugeng Wibowo 4 Mar 23, 2022
🌾 Harvest: Apple's Combine.framework + State Machine, inspired by Elm.

NOTE: This repository has been discontinued in favor of Actomaton. ?? Harvest Apple's Combine.framework (from iOS 13) + State Machine, inspired by Elm

Yasuhiro Inami 386 Dec 18, 2022
A lightweight, event-driven architectural framework

Trellis Trellis features a declarative DSL that simplifies service bootstrapping: let cluster = try await Bootstrap { Group { Store(model:

Valentin Radu 25 Aug 16, 2022