# CombineExt
**Repository Path**: cc2000kk/CombineExt
## Basic Information
- **Project Name**: CombineExt
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-12-17
- **Last Updated**: 2021-12-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# CombineExt
CombineExt provides a collection of operators, publishers and utilities for Combine, that are not provided by Apple themselves, but are common in other Reactive Frameworks and standards.
The original inspiration for many of these additions came from my journey investigating Combine after years of RxSwift and ReactiveX usage.
All operators, utilities and helpers respect Combine's publisher contract, including backpressure.
### Operators
* [withLatestFrom](#withLatestFrom)
* [flatMapLatest](#flatMapLatest)
* [assign](#assign)
* [amb and Collection.amb](#amb)
* [materialize](#materialize)
* [values](#values)
* [failures](#failures)
* [dematerialize](#dematerialize)
* [partition](#partition)
* [zip(with:) and Collection.zip](#ZipMany)
* [Collection.merge()](#MergeMany)
* [combineLatest(with:) and Collection.combineLatest](#CombineLatestMany)
* [mapMany(_:)](#MapMany)
* [filterMany(_:)](#FilterMany)
* [setOutputType(to:)](#setOutputType)
* [removeAllDuplicates and removeAllDuplicates(by:) ](#removeAllDuplicates)
* [share(replay:)](#sharereplay)
* [prefix(duration:tolerance:on:options:)](#prefixduration)
* [toggle()](#toggle)
* [nwise(_:) and pairwise()](#nwise)
* [ignoreOutput(setOutputType:)](#ignoreOutputsetOutputType)
* [ignoreFailure](#ignoreFailure)
* [mapToResult](#mapToResult)
* [flatMapBatches(of:)](#flatMapBatchesof)
### Publishers
* [AnyPublisher.create](#AnypublisherCreate)
* [CurrentValueRelay](#CurrentValueRelay)
* [PassthroughRelay](#PassthroughRelay)
### Subjects
* [ReplaySubject](#ReplaySubject)
> **Note**: This is still a relatively early version of CombineExt, with much more to be desired. I gladly accept PRs, ideas, opinions, or improvements. Thank you! :)
## Installation
### CocoaPods
Add the following line to your **Podfile**:
```rb
pod 'CombineExt'
```
### Swift Package Manager
Add the following dependency to your **Package.swift** file:
```swift
.package(url: "https://github.com/CombineCommunity/CombineExt.git", from: "1.0.0")
```
### Carthage
Carthage support is offered as a prebuilt binary.
Add the following to your **Cartfile**:
```
github "CombineCommunity/CombineExt"
```
## Operators
This section outlines some of the custom operators CombineExt provides.
### withLatestFrom
Merges up to four publishers into a single publisher by combining each value from `self` with the _latest_ value from the other publishers, if any.
```swift
let taps = PassthroughSubject()
let values = CurrentValueSubject("Hello")
taps
.withLatestFrom(values)
.sink(receiveValue: { print("withLatestFrom: \($0)") })
taps.send()
taps.send()
values.send("World!")
taps.send()
```
#### Output:
```none
withLatestFrom: Hello
withLatestFrom: Hello
withLatestFrom: World!
```
------
### flatMapLatest
Transforms an output value into a new publisher, and flattens the stream of events from these multiple upstream publishers to appear as if they were coming from a single stream of events.
Mapping to a new publisher will cancel the subscription to the previous one, keeping only a single subscription active along with its event emissions.
**Note**: `flatMapLatest` is a combination of `map` and `switchToLatest`.
```swift
let trigger = PassthroughSubject()
trigger
.flatMapLatest { performNetworkRequest() }
trigger.send()
trigger.send() // cancels previous request
trigger.send() // cancels previous request
```
------
### assign
CombineExt provides custom overloads of `assign(to:on:)` that let you bind a publisher to multiple keypath targets simultaneously.
```swift
var label1: UILabel
var label2: UILabel
var text: UITextField
["hey", "there", "friend"]
.publisher
.assign(to: \.text, on: label1,
and: \.text, on: label2,
and: \.text, on: text)
```
CombineExt provides an additional overload — `assign(to:on:ownership)` — which lets you specify the kind of ownersip you want for your assign operation: `strong`, `weak` or `unowned`.
```swift
// Retain `self` strongly
subscription = subject.assign(to: \.value, on: self)
subscription = subject.assign(to: \.value, on: self, ownership: .strong)
// Use a `weak` reference to `self`
subscription = subject.assign(to: \.value, on: self, ownership: .weak)
// Use an `unowned` reference to `self`
subscription = subject.assign(to: \.value, on: self, ownership: .unowned)
```
------
### amb
Amb takes multiple publishers and mirrors the first one to emit an event. You can think of it as a race of publishers, where the first one to emit passes its events, while the others are ignored (there’s also a `Collection.amb` method to ease working with multiple publishers).
The name `amb` comes from the [Reactive Extensions operator](http://reactivex.io/documentation/operators/amb.html), also known in RxJS as `race`.
```swift
let subject1 = PassthroughSubject()
let subject2 = PassthroughSubject()
subject1
.amb(subject2)
.sink(receiveCompletion: { print("amb: completed with \($0)") },
receiveValue: { print("amb: \($0)") })
subject2.send(3) // Since this subject emit first, it becomes the active publisher
subject1.send(1)
subject2.send(6)
subject1.send(8)
subject1.send(7)
subject1.send(completion: .finished)
// Only when subject2 finishes, amb itself finishes as well, since it's the active publisher
subject2.send(completion: .finished)
```
#### Output:
```none
amb: 3
amb: 6
amb: completed with .finished
```
------
### materialize
Convert any publisher to a publisher of its events. Given a `Publisher