Giter Club home page Giter Club logo

combinex's Introduction

CombineX

Github CI Status Release Install Supported Platform Discord

简体中文

Open-source implementation of Apple's Combine for processing values over time.

Though CombineX have implemented all the Combine interface, the project is still in early development.

What is Combine

Customize handling of asynchronous events by combining event-processing operators. -- Apple

Combine is a Functional Reactive Programming (FRP) framework launched by Apple at WWDC 2019. It will definitely be the cornerstone of Swift programming in the foreseeable future.

Get Started

If you develop a library, it's recommended to use CXShim so your library is compatible with SwiftUI.

Requirements

  • Swift 5.0+ (Xcode 10.2+)

Installation

Swift Package Manager (Recommended)

package.dependencies += [
    .package(url: "https://github.com/cx-org/CombineX", from: "0.4.0"),
]

CocoaPods

pod 'CombineX', "~> 0.4.0"

# or, if you want to use `Foundation` extensions: 
pod 'CombineX/CXFoundation', "~> 0.4.0"

Carthage

github "cx-org/CombineX" ~> 0.4.0

Related Projects

These libraries bring additional functionality to Combine. They are all Combine Compatible Package and you're free to switch underlying Combine implementation between CombineX and Apple's Combine.

  • CXTest: test infrastructure for Combine. It provides useful test utilities like TracingSubscriber and VirtualTimeScheduler.
  • CXExtensions: provides a collection of useful extensions for Combine, such as IgnoreError, DelayedAutoCancellable, etc.
  • CXCocoa: provides Combine extensions to Cocoa, such as KVO+Publisher, Method Interception, UIBinding, Delegate Proxy, etc.

License

CombineX is released under the MIT license. See LICENSE for details.

The following files are adapted from the Swift open source project:

combinex's People

Contributors

ddddxxx avatar franzbusch avatar garvankeeley avatar josephduffy avatar luoxiu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

combinex's Issues

Debounce keeps emitting values even though debounced publisher is not publishing

Debounce seems to get into an endless loop emitting last received value.
This code:

 let pub = PassthroughSubject<Int, Never>()
        
        pub
            .debounce(for: 1.0, scheduler: DispatchQueue.main.cx)
            .sink(receiveValue: {
                print("received: \($0) at: \(Date())")
            })
            .store(in: &subscribers)
        
        (0...10).forEach(pub.send)

Gives this result:

received: 10 at: 2019-11-07 10:16:58 +0000
received: 10 at: 2019-11-07 10:16:59 +0000
received: 10 at: 2019-11-07 10:17:00 +0000
received: 10 at: 2019-11-07 10:17:01 +0000
received: 10 at: 2019-11-07 10:17:02 +0000
received: 10 at: 2019-11-07 10:17:03 +0000
received: 10 at: 2019-11-07 10:17:04 +0000
received: 10 at: 2019-11-07 10:17:05 +0000
received: 10 at: 2019-11-07 10:17:06 +0000
received: 10 at: 2019-11-07 10:17:07 +0000
received: 10 at: 2019-11-07 10:17:08 +0000
received: 10 at: 2019-11-07 10:17:09 +0000
received: 10 at: 2019-11-07 10:17:10 +0000
received: 10 at: 2019-11-07 10:17:11 +0000
received: 10 at: 2019-11-07 10:17:12 +0000
received: 10 at: 2019-11-07 10:17:13 +0000
received: 10 at: 2019-11-07 10:17:14 +0000

Build failure when use CXShim + Combine + iOS (No such module 'Combine')

When use CXShim with system Combine and target on 'Any iOS Device', we got "No such module 'Combine'" error. As reported in #116 and sbertix/Swiftagram#191.

This is because CXShim always have low system requirement. To re-export system Combine, we need to bump platform to iOS 13.0.

However, system requirement is applied to both CombineX and CXShim. We can make it configurable via environment variable, but we can't make them both work out of the box. Currently CX_CONTINUOUS_INTEGRATION=YES CX_COMBINE_IMPLEMENTATION=Combine will force high platform and CX_COMBINE_IMPLEMENTATION=CombineX will force low platform.

I believe CombineX and CXShim are equally important. Mandatory env configuration can make integration significantly more obscure. The best solution I can think of is to move CXShim to a separate repo. So we can lift system requirement just for CXShim. This would be a breaking change.

Update Package.swift to Swift 5.3

Would be great to get this updated if possible. My main reason for advocating for this is to avoid consumers (myself included) from having test dependencies included, since this was resolved in the most recent update.

consider adapting Apple's implementations of Foundation and Dispatch publishers

Apple's implementations of the Foundation and Dispatch publishers and schedulers are part of the Swift open-source project. Have you considered adapting those implementations for CX?

Here are the files of interest:

Crash when demangling Failure

Hi! I am not sure if this is indeed a CombineX issue, but it crashes when running on device when subscribing to a publisher inside a propertywrapper.

The message is:

failed to demangle witness for associated type 'Failure' in conformance 'CombineX.Publishers.Drop<CombineX.CurrentValueSubject<Swift.Optional<Swift.String>, Swift.Never>>: Publisher' from mangled name '7Failure8CombineX9PublisherPQz'

The code is this

import Foundation
import CXFoundation

@propertyWrapper
struct StoredObservable<Key: StringProtocol, Value: Codable> {

    private var store: DataCaching
    private var key: Key
    private var value: Value?

    private var publisher: CurrentValueSubject<Value?, Never>
    private var subscriber: AnyCancellable

    var wrappedValue: Value? {
        get {
            return value
        }
        set {
            value = newValue
            publisher.send(newValue)
        }
    }

    var projectedValue: CurrentValueSubject<Value?, Never> {
        mutating get {
            return publisher
        }
    }

    init(_ key: Key, _ store: DataCaching) {

        let compositeKey: Key = "StoredObservable.\(key)"

        self.key = compositeKey
        self.store = store
        self.value = store.fetchCachedValue(forKey: String(compositeKey), ofType: Value.self)
        publisher = .init(self.value)
        self.subscriber = publisher
            .dropFirst()
            .sink(receiveCompletion: { _ in }, receiveValue: {
                do {
                    try store.setCachedValue($0, forKey: String(compositeKey))
                } catch {
                    print(error)
                    assertionFailure()
                }
            })

    }
}

and it crashes here:

image

Update: This doesn't seem to be caused by the property wrapper context at all. I seem to hit this a lot now.

@luoxiu Do you have any idea what causes failed to demangle witness for associated type 'Failure' in conformance and how I might avoid it?

Set Environment Variable CX_COMBINE_IMPLEMENTATION = "CombineX" for CI

Hi,

Environment variables seem tricky and Xcode doesn't seem to recognize them (I'm trying Environment Variables setting under executable target scheme). I am wondering why didn't you choose launch arguments instead (under executable target scheme) ?

PS: It works if I set environment variable before launching Xcode though.

Thanks for helping!

Shahzad

Build errors: missing Lock.swift, Extensions.swift in CXUtility

Seeing errors about missing files building from master:

error: Build input files cannot be found: 'Carthage/Checkouts/CombineX/Sources/CXUtility/Extensions.swift', 'Carthage/Checkouts/CombineX/Sources/CXUtility/Lock.swift' (in target 'CXUtility_iOS' from project 'CombineX-Carthage'

Rename `CXWrappers` -> `CX`

CXWrappers is a misleading namespace, and it leaks implementation detail. When use with system Combine, CXWrappers.DispatchQueue is simply a typealias to DispatchQueue and doesn't wrap anything.

I think CX is a better namespace, also CX.DispatchQueue is symmetrical with DispatchQueue.CX.

Format `swift test` output on CI

I'm using xcbeautify for my personal project, here is my workflow: https://github.com/Cyberbeni/TypedNotificationCenter/blob/c7c60960468e939008f15a2984d7e90953a6e726/.github/workflows/run_tests.yml#L6
Here is how the output looks: https://github.com/Cyberbeni/TypedNotificationCenter/runs/1289031608?check_suite_focus=true#step:4:31

xcbeautify works for both macOS and Linux, install-swift-tool takes care of building and caching of xcbeautify, so consecutive runs will only have a couple seconds of overhead for downloading it.

Merging efforts

Hi,

Thank you for tackling the combine requirements issue. I believe this will help a lot but will require a lot of contributions.

There is another port being build at https://github.com/broadwaylamb/OpenCombine.
Maybe you could merge yours efforts ? I'm opening the same issue on the other repo.

Crash when using debounce (100%)

Hi, in a very simple use case debounce seems to crash, but it might just be me using the cx proxy wrong?

This code crashes with EXC_BAD_INSTRUCTION:

 let pub = PassthroughSubject<Int, Never>()
        
        pub
            .debounce(for: 2.0, scheduler: DispatchQueue.global().cx)
            .sink(receiveValue: {
                print($0)
            })
            .store(in: &subscribers)
        
        (0...10).forEach(pub.send) //Crashes here: Thread 1: EXC_BAD_INSTRUCTION

Zip3 Operator

Hi,

I am trying to test Zip3 operator and it doesn't seem to be working as expected:

My Code:

`var disposable: [AnyCancellable] = []
func testZip3() {

    let p1 = [3, 4, 5].cx.publisher
    let p2 = ["Hello", "World"].cx.publisher
    let p3 = [0.2, 0.6].cx.publisher

    Publishers.Zip3(p1, p2, p3)
    .print()
    .sink(receiveCompletion: { result in
        print(result)
    }, receiveValue: { (r1, r2, r3) in
        print(r1, r2, r3)
    })
    .store(in: &disposable)
}`

Output:
: receive subscription: (MapError) : request unlimited : receive finished finished

PS: Same code works fine when I use Apple Combine.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.