Skip to content

Combine Compatible Package

ddddxxx edited this page Feb 16, 2020 · 17 revisions

A Combine compatible package let you choose underlying Combine implementation, without modifying any code / package description.

List of Combine compatible packages.

Why

It's common to use open souces Combine implementaion as a Combine polyfill on lower version macOS, iOS, and Linux.

For cross platform applications, You need lots of compilation conditions, like this:

Boilerplate Code
// in Package.swift
#if canImport(Combine)
let packageDependencies: [Package.Dependency] = []
let targetDependencies: [Target.Dependency] = []
#else
let packageDependencies = [Package.Dependency.package(url: "https://github.com/cx-org/CombineX", ...]
let targetDependencies: [Target.Dependency] = ["CombineX"]
#endif
// config package accordingly

// in code
#if canImport(Combine)
import Combine
#else
import CombineX
#endif

It's not that simple for libraries. Once you choose system Combine, there's no way you can use open source Combine implementation for backwards deployment. In contrast, once you choose open source Combine to support lower version OS, you have to bundle the whole third party Combine, even your client targets on new OS version.

Further more, no matter which Combine implementation you choose for whatever platform, you are forcing you client to do the same choice. Even worse, If two libraries make different choice, they are inherently incompatiable!

Solution

Introducing CXShim. It dynamically choose appropriate Combine implementation at build time according to environment variable. You only need one single dependency, no more compilation conditions.

Example
// in Package.swift
let package = Package(
    name: "MyAwesomePackage",
    ...
    dependencies: [
        .package(url: "https://github.com/cx-org/CombineX", ...),
    ],
    targets: [
        .target(name: "MyAwesomePackage", dependencies: ["CXShim"]),
    ]
}

// in code
import CXShim // Thats all!

Usage

You can specify underlying Combine implementation via environment variable CX_COMBINE_IMPLEMENTATION.

  • Set CX_COMBINE_IMPLEMENTATION="CombineX" to use CombineX.
  • Set CX_COMBINE_IMPLEMENTATION="Combine" to use Apple's Combine.
$ export CX_COMBINE_IMPLEMENTATION="CombineX"

# for CLI tools, execute with env variable
$ swift ...
$ xcodebuild ...

# for Xcode GUI, reopen Xcode with env variable
$ killall Xcode
$ open Package.swift

If no environment variable is set, CXShim automatically select appropriate Combine implementation.

Especially, on Apple's platform, Combine is preferred, so you won't accidentally introduce third party dependency, unless you / your client explicitly specified.

Other Combine Implementation

Disclaimer: These project are not part of CombineX. They may have different consistent level with Apple's Combine than we promised, and not necessarily pass our test suit. We do not make any warranty of any kind for them.

Library Value of CX_COMBINE_IMPLEMENTATION
OpenCombine OpenCombine
Clone this wiki locally