Skip to content

Instantly share code, notes, and snippets.

@tadija
Last active May 13, 2021 16:04
Show Gist options
  • Save tadija/8c307aa9a0590ab946c0715ebe8a50b2 to your computer and use it in GitHub Desktop.
Save tadija/8c307aa9a0590ab946c0715ebe8a50b2 to your computer and use it in GitHub Desktop.
AECombine
/**
* https://gist.github.com/tadija/8c307aa9a0590ab946c0715ebe8a50b2
* Revision 2
* Copyright © 2021 Marko Tadić
* Licensed under the MIT license
*/
import Foundation
import Combine
public extension Publisher {
func sink() -> AnyCancellable {
self.sink(
receiveCompletion: { _ in },
receiveValue: { _ in }
)
}
}
public extension Publisher {
func mapToVoid() -> AnyPublisher<Void, Self.Failure> {
self.map { _ in () }
.eraseToAnyPublisher()
}
}
public extension Subscribers.Completion {
func mapToResult() -> Result<Void, Error> {
switch self {
case .finished:
return .success(())
case .failure(let error):
return .failure(error)
}
}
}
/// - See: https://www.swiftbysundell.com/articles/combine-self-cancellable-memory-management
public extension Publisher where Failure == Never {
func weakAssign<T: AnyObject>(
to keyPath: ReferenceWritableKeyPath<T, Output>,
on object: T
) -> AnyCancellable {
sink { [weak object] value in
object?[keyPath: keyPath] = value
}
}
}
/// - See: https://www.swiftbysundell.com/articles/connecting-and-merging-combine-publishers-in-swift
public extension Publisher where Output: Sequence {
typealias Sorter = (Output.Element, Output.Element) -> Bool
func sort(
by sorter: @escaping Sorter
) -> Publishers.Map<Self, [Output.Element]> {
map { sequence in
sequence.sorted(by: sorter)
}
}
}
/// - See: https://www.swiftbysundell.com/articles/extending-combine-with-convenience-apis
public extension Publisher where Output == Data {
func decode<T: Decodable>(
as type: T.Type = T.self,
using decoder: JSONDecoder = .init()
) -> Publishers.Decode<Self, T, JSONDecoder> {
decode(type: type, decoder: decoder)
}
}
public extension Publisher where Output: Encodable {
func encode(
using encoder: JSONEncoder = .init()
) -> Publishers.Encode<Self, JSONEncoder> {
encode(encoder: encoder)
}
}
public extension Publisher {
func validate(
using validator: @escaping (Output) throws -> Void
) -> Publishers.TryMap<Self, Output> {
tryMap { output in
try validator(output)
return output
}
}
}
public extension Publisher {
func unwrap<T>(
orThrow error: @escaping @autoclosure () -> Failure
) -> Publishers.TryMap<Self, T> where Output == Optional<T> {
tryMap { output in
switch output {
case .some(let value):
return value
case nil:
throw error()
}
}
}
}
public extension Publisher {
func convertToResult() -> AnyPublisher<Result<Output, Failure>, Never> {
self.map(Result.success)
.catch { Just(.failure($0)) }
.eraseToAnyPublisher()
}
}
public extension AnyPublisher {
static func just(_ output: Output) -> Self {
Just(output)
.setFailureType(to: Failure.self)
.eraseToAnyPublisher()
}
static func fail(with error: Failure) -> Self {
Fail(error: error).eraseToAnyPublisher()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment