Skip to content

Commit

Permalink
refactor(*): cleanup and add documentation when needed
Browse files Browse the repository at this point in the history
  • Loading branch information
hadiidbouk committed Nov 1, 2024
1 parent e72437a commit a2c80f8
Show file tree
Hide file tree
Showing 29 changed files with 478 additions and 434 deletions.
6 changes: 1 addition & 5 deletions Sources/FueledUtils/Combine/AnyCurrentValuePublisher.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2020, Fueled Digital Media, LLC
// Copyright © 2024 Fueled Digital Media, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -20,7 +20,6 @@ import Combine
/// Use an `AnyCurrentValuePublisher` to wrap an existing current value publisher whose details you don’t want to expose.
/// For example, this is useful if you want to use a `CurrentValueSubject` internally, but don't want to expose the setter/its send() method
///
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public struct AnyCurrentValuePublisher<Output, Failure: Swift.Error>: CurrentValuePublisher {
private let valueGetter: () -> Output
private let receiveSubscriberClosure: (AnySubscriber<Output, Failure>) -> Void
Expand All @@ -44,7 +43,6 @@ public struct AnyCurrentValuePublisher<Output, Failure: Swift.Error>: CurrentVal
}
}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension CurrentValuePublisher {
public func eraseToAnyCurrentValuePublisher() -> AnyCurrentValuePublisher<Output, Failure> {
AnyCurrentValuePublisher(self)
Expand All @@ -54,11 +52,9 @@ extension CurrentValuePublisher {
///
/// A publisher that also stores the last value it sent
///
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol CurrentValuePublisher: Publisher {
var value: Output { get }
}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension CurrentValueSubject: CurrentValuePublisher {
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2020, Fueled Digital Media, LLC
// Copyright © 2024 Fueled Digital Media, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,6 @@ import Combine
import Foundation
import FueledUtilsCore

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension ObservableObject where Self.ObjectWillChangePublisher == ObservableObjectPublisher {
// Perform a one-way link, where the receiver will listen for changes on the object and automatically trigger its `objectWillChange` publisher
public func link<Object: ObservableObject>(to object: Object) {
Expand Down Expand Up @@ -77,7 +76,6 @@ extension ObservableObject where Self.ObjectWillChangePublisher == ObservableObj
}
}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension ObservableObject {
public var objectDidChange: AnyPublisher<Self.ObjectWillChangePublisher.Output, Never> {
// The delay of 0.0 allows the will to transform into a Did, by waiting for exactly one run loop cycle
Expand All @@ -89,7 +87,6 @@ extension ObservableObject {
}
}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension Publisher where Output: Collection, Failure == Never, Output.Element: ObservableObject {
public func onAnyChanges() -> AnyPublisher<[Output.Element], Never> {
self.flatMap { Publishers.CombineLatestMany($0.map { $0.publisher }) }.eraseToAnyPublisher()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright © 2024 Fueled Digital Media, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Combine


public extension Publisher {
/// A tuple type that holds the previous and current output values of a publisher.
typealias CombinePreviousOutput = (previous: Output, current: Output)

///
/// Combines the previous and current output values of the publisher, starting with a nil initial value.
///
/// This method emits a tuple containing the previous and current values
/// whenever the publisher emits a new value. If no previous value exists,
/// the publisher will complete without emitting any output.
///
/// - Returns: An `AnyPublisher<CombinePreviousOutput, Failure>` that emits
/// tuples of previous and current output values.
///
func combinePrevious() -> AnyPublisher<CombinePreviousOutput, Failure> {
combinePreviousImplementation(nil)
}

///
/// Combines the previous and current output values of the publisher, starting with a specified initial value.
///
/// This method allows you to track values from the very beginning,
/// emitting a tuple of previous and current values whenever the publisher emits a new value.
///
/// - Parameter initial: The initial value to use as the previous output
/// for the first emission.
/// - Returns: An `AnyPublisher<CombinePreviousOutput, Failure>` that emits
/// tuples of previous and current output values.
///
func combinePrevious(_ initial: Output) -> AnyPublisher<CombinePreviousOutput, Failure> {
combinePreviousImplementation(initial)
}
}

private extension Publisher {
///
/// The implementation for combining previous and current output values.
///
/// This method uses the `scan` operator to keep track of the previous
/// and current values, returning a publisher that emits a tuple of both
/// values whenever a new value is emitted. If the initial value is nil
/// and there is no previous value, the publisher completes without emitting.
///
/// - Parameter initial: The initial value to use as the previous output.
/// - Returns: An `AnyPublisher<CombinePreviousOutput, Failure>` that emits
/// tuples containing the previous and current output values or completes
/// without emitting if there is no previous value available.
///
func combinePreviousImplementation(_ initial: Output?) -> AnyPublisher<CombinePreviousOutput, Failure> {
scan((Output?.none, initial)) { current, newValue in
(current.1, newValue)
}
.map { previous, current -> AnyPublisher<CombinePreviousOutput, Failure> in
if let previous {
let output = CombinePreviousOutput(previous, current!)
return Just(output)
.setFailureType(to: Failure.self)
.eraseToAnyPublisher()
} else {
return Empty(completeImmediately: false)
.eraseToAnyPublisher()
}
}
.switchToLatest()
.eraseToAnyPublisher()
}
}
Loading

0 comments on commit a2c80f8

Please sign in to comment.