diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 01157f8..15d5b83 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,10 +1,10 @@ PODS: - GradientLoadingBar (2.0.1): - - LightweightObservable (~> 1.0) - - LightweightObservable (1.0.3) + - LightweightObservable (~> 2.0) + - LightweightObservable (2.0.0) - SnapshotTesting (1.6.0) - - SwiftFormat/CLI (0.40.13) - - SwiftLint (0.36.0) + - SwiftFormat/CLI (0.41.2) + - SwiftLint (0.37.0) DEPENDENCIES: - GradientLoadingBar (from `../`) @@ -24,11 +24,11 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - GradientLoadingBar: 4ef091b906199ffe5cec36f51aa45953d9b3e69e - LightweightObservable: 8687e8e1e2940ae2f64d7f71fe78c036d89c966f + GradientLoadingBar: f9e97f00d11c16021c2b232a9799544c3429a146 + LightweightObservable: f0c032384379a17cb048b861e33de8209155d7be SnapshotTesting: 9f478335073a830eafb7dc1fcd526c5e90143991 - SwiftFormat: d548b3585a6dbe64390177b386e95375b8c300b6 - SwiftLint: fc9859e4e1752340664851f667bb1898b9c90114 + SwiftFormat: 09921e624a7c5c53a687a9ae625fee48071a5d71 + SwiftLint: c078a14d7d7ade75e5507795d185e3da41d844d2 PODFILE CHECKSUM: f56a08d884831d712155be32578b7364270d0af0 diff --git a/Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable/Observable+Equatable.swift b/Example/Pods/LightweightObservable/LightweightObservable/Classes/Extensions/Observable+Equatable.swift similarity index 77% rename from Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable/Observable+Equatable.swift rename to Example/Pods/LightweightObservable/LightweightObservable/Classes/Extensions/Observable+Equatable.swift index 13dac46..5c5f3d3 100644 --- a/Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable/Observable+Equatable.swift +++ b/Example/Pods/LightweightObservable/LightweightObservable/Classes/Extensions/Observable+Equatable.swift @@ -13,7 +13,7 @@ public extension Observable where T: Equatable { // MARK: - Types /// The type for the filter closure. - typealias Filter = (NewValue, OldValue) -> Bool + typealias Filter = (Value, OldValue) -> Bool // MARK: - Public methods @@ -23,10 +23,10 @@ public extension Observable where T: Equatable { /// - filter: The filer-closure, that must return `true` in order for the observer to be notified. /// - observer: The observer-closure that is notified on changes. func subscribe(filter: @escaping Filter, observer: @escaping Observer) -> Disposable { - return subscribe { nextValue, prevValue in - guard filter(nextValue, prevValue) else { return } + subscribe { newValue, oldValue in + guard filter(newValue, oldValue) else { return } - observer(nextValue, prevValue) + observer(newValue, oldValue) } } @@ -34,7 +34,7 @@ public extension Observable where T: Equatable { /// /// - Parameter observer: The observer-closure that is notified on changes. func subscribeDistinct(_ observer: @escaping Observer) -> Disposable { - return subscribe(filter: { $0 != $1 }, - observer: observer) + subscribe(filter: { $0 != $1 }, + observer: observer) } } diff --git a/Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable.swift b/Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable.swift new file mode 100644 index 0000000..e2985c8 --- /dev/null +++ b/Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable.swift @@ -0,0 +1,159 @@ +// +// Observable.swift +// LightweightObservable +// +// Created by Felix Mau on 11/02/19. +// Copyright © 2019 Felix Mau. All rights reserved. +// + +import Foundation + +/// An observable sequence that you can subscribe to. +/// +/// - Note: Implementation is partly based on [roberthein/Observable](https://github.com/roberthein/Observable). +public class Observable { + // MARK: - Types + + /// The type for the new value of the observable. + public typealias Value = T + + /// The type for the previous value of the observable. + public typealias OldValue = T? + + /// The type for the closure to executed on change of the observable. + public typealias Observer = (Value, OldValue) -> Void + + /// We store all observers within a dictionary, for which this is the type of the key. + private typealias Index = UInt + + // MARK: - Public properties + + /// The current (readonly) value of the observable (if available). + /// + /// - Note: We're using a computed property here, cause we need to override this property without nullability in the subclass `Variable`. + /// + /// - Attention: It's always better to subscribe to a given observable! This **shortcut** should only be used during **testing**. + public var value: Value? { + fatalError("⚠️ – Subclasses need to overwrite this computed property.") + } + + // MARK: - Private properties + + /// The index of the last inserted observer. + private var lastIndex: Index = 0 + + /// Map with all active observers. + private var observers = [Index: Observer]() + + // MARK: - Initalizer + + /// Initializes a new observable. + /// + /// - Note: Declared `fileprivate` in order to prevent directly initializing an observable, which can not be updated. + fileprivate init() { + // swiftformat:disable:previous redundantFileprivate + } + + // MARK: - Public methods + + /// Informs the given observer on changes to our `value`. + /// + /// - Parameter observer: The observer-closure that is notified on changes. + public func subscribe(_ observer: @escaping Observer) -> Disposable { + let currentIndex = lastIndex + 1 + observers[currentIndex] = observer + lastIndex = currentIndex + + // Return a disposable, that removes the entry for this observer on it's deallocation. + return Disposable { [weak self] in + self?.observers[currentIndex] = nil + } + } + + // MARK: - Private methods + + fileprivate func notifyObserver(_ value: Value, oldValue: OldValue) { + for (_, observer) in observers { + observer(value, oldValue) + } + } +} + +/// Starts empty and only emits new elements to subscribers. +public final class PublishSubject: Observable { + // MARK: - Public properties + + /// The current (readonly) value of the observable (if available). + public override var value: Value? { + currentValue + } + + // MARK: - Private properties + + /// The storage for our computed property. + private var currentValue: Value? + + // MARK: - Initializer + + /// Initializes a new publish subject. + /// + /// - Note: As we've made the initializer to the super class `Observable` fileprivate, we must override it here to allow public access. + public override init() { + super.init() + } + + // MARK: - Public methods + + /// Updates the publish subject using the given value. + public func update(_ value: Value) { + let oldValue = currentValue + currentValue = value + + // We inform the observer here instead of using `didSet` to prevent unwrapping an optional (`currentValue` is nullable, as we're starting empty!). + notifyObserver(value, oldValue: oldValue) + } +} + +/// Starts with an initial value and replays it or the latest element to new subscribers. +public final class Variable: Observable { + // MARK: - Public properties + + /// The current (read- and writeable) value of the variable. + public override var value: Value { + get { + currentValue + } + set { + currentValue = newValue + } + } + + // MARK: - Private properties + + /// The storage for our computed property. + private var currentValue: Value { + didSet { + notifyObserver(value, oldValue: oldValue) + } + } + + // MARK: - Initializer + + /// Initializes a new variable with the given value. + /// + /// - Note: We keep the initializer to the super class `Observable` fileprivate in order to verify always having a value. + public init(_ value: Value) { + currentValue = value + + super.init() + } + + // MARK: - Public methods + + public override func subscribe(_ observer: @escaping Observer) -> Disposable { + // A variable should inform the observer with the initial value. + observer(value, nil) + + return super.subscribe(observer) + } +} diff --git a/Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable/Observable.swift b/Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable/Observable.swift deleted file mode 100644 index 5ae3bd9..0000000 --- a/Example/Pods/LightweightObservable/LightweightObservable/Classes/Observable/Observable.swift +++ /dev/null @@ -1,110 +0,0 @@ -// -// Observable.swift -// LightweightObservable -// -// Created by Felix Mau on 11/02/19. -// Copyright © 2019 Felix Mau. All rights reserved. -// - -import Foundation - -/// An observable sequence that you can subscribe to. Any of the subscriber will receive the most -/// recent element and everything that is emitted by that sequence after the subscription happened. -/// -/// - Note: Implementation based on [roberthein/Observable](https://github.com/roberthein/Observable). -public class Observable { - // MARK: - Types - - /// The type for the new value of the observable. - public typealias NewValue = T - - /// The type for the previous value of the observable. - public typealias OldValue = T? - - /// The type for the closure to executed on change of the observable. - public typealias Observer = (NewValue, OldValue) -> Void - - /// We store all observers within a dictionary, for which this is the type of the key. - private typealias Index = UInt - - // MARK: - Public properties - - /// The current (readonly) value of the observable. - public fileprivate(set) var value: T { - didSet { - for (_, observer) in observers { - observer(value, oldValue) - } - } - } - - // MARK: - Private properties - - /// The index of the last inserted observer. - private var lastIndex: Index = 0 - - /// Map with all active observers. - private var observers = [Index: Observer]() - - // MARK: - Initalizer - - /// Initializes a new observable with the given value. - /// - /// - Note: Declared `fileprivate` in order to prevent directly initializing an observable, which can not be updated. - fileprivate init(_ value: T) { - // swiftformat:disable:previous redundantFileprivate - self.value = value - } - - // MARK: - Public methods - - /// Informs the given observer on changes to our `value`. - /// - /// - Parameter observer: The observer-closure that is notified on changes. - public func subscribe(_ observer: @escaping Observer) -> Disposable { - let currentIndex = lastIndex + 1 - observers[currentIndex] = observer - - lastIndex = currentIndex - - // Inform observer with initial value. - observer(value, nil) - - // Return a disposable, that removes the entry for this observer on it's deallocation. - return Disposable { [weak self] in - self?.observers[currentIndex] = nil - } - } -} - -/// A special form of an observable sequence, that you can subscribe to AND dynamically add elements. -/// -/// - Note: Has to be declared in the same file as `Observable`, to overwrite `fileprivate` setter for property `value`. -/// (Workaround for a "protected" property). -public final class Variable: Observable { - // MARK: - Public properties - - /// The current variable converted to an (readonly) `Observable`. - public var asObservable: Observable { - return self as Observable - } - - /// The current value of the observable. - public override var value: T { - get { - return super.value - } - set { - super.value = newValue - } - } - - // MARK: - Initializer - - /// Initializes a new variable with the given value. - /// - /// - Note: As we've made the initializer to the super class `Observable` fileprivate, we must override it here with public access. - public override init(_ value: T) { - super.init(value) - } -} diff --git a/Example/Pods/LightweightObservable/README.md b/Example/Pods/LightweightObservable/README.md index b94f0cb..2c94095 100644 --- a/Example/Pods/LightweightObservable/README.md +++ b/Example/Pods/LightweightObservable/README.md @@ -11,9 +11,14 @@ ## Features -Lightweight Obserservable is a simple implementation of an observable sequence that you can subscribe to. The framework is designed to be minimal meanwhile convenient. The entire code is only ~80 lines (excluding comments). With Lightweight Observable you can easily set up UI-Bindings in an MVVM application, handle asynchronous network calls and a lot more. +Lightweight Observable is a simple implementation of an observable sequence that you can subscribe to. The framework is designed to be minimal meanwhile convenient. The entire code is only ~90 lines (excluding comments). With Lightweight Observable you can easily set up UI-Bindings in an MVVM application, handle asynchronous network calls and a lot more. -**Credits:** The code was heavily influenced by [roberthein/observable](https://github.com/roberthein/Observable). However I needed something that was syntactically closer to [RxSwift](https://github.com/ReactiveX/RxSwift), which is why I came up with this code, and for reusability reasons afterwards moved it into a CocoaPod. +##### Credits +The code was heavily influenced by [roberthein/observable](https://github.com/roberthein/Observable). However I needed something that was syntactically closer to [RxSwift](https://github.com/ReactiveX/RxSwift), which is why I came up with this code, and for re-usability reasons afterwards moved it into a CocoaPod. + +##### Migration Guide +If you want to update from version 1.x.x, please have a look at the [Lightweight Observable 2.0 Migration Guide +](Documentation/Lightweight%20Observable%202.0%20Migration%20Guide.md) ### Example To run the example project, clone the repo, and open the workspace from the Example directory. @@ -21,14 +26,16 @@ To run the example project, clone the repo, and open the workspace from the Exam ### Integration ##### CocoaPods [CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Lightweight Observable into your Xcode project using CocoaPods, specify it in your `Podfile`: + ```ruby -pod 'LightweightObservable', '~> 1.0' +pod 'LightweightObservable', '~> 2.0' ``` ##### Carthage [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate Lightweight Observable into your Xcode project using Carthage, specify it in your `Cartfile`: + ```ogdl -github "fxm90/LightweightObservable" ~> 1.0 +github "fxm90/LightweightObservable" ~> 2.0 ``` Run carthage update to build the framework and drag the built `LightweightObservable.framework` into your Xcode project. @@ -37,95 +44,62 @@ Run carthage update to build the framework and drag the built `LightweightObserv The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but Lightweight Observable does support its use on supported platforms. Once you have your Swift package set up, adding Lightweight Observable as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`. + ```swift dependencies: [ - .package(url: "https://github.com/fxm90/LightweightObservable", from: "1.0.3") + .package(url: "https://github.com/fxm90/LightweightObservable", from: "2.0.0") ] ``` ### How to use -The framework provides two classes `Observable` and `Variable`: - - `Observable`: Contains an immutable value, you only can subscribe to. This is useful in order to avoid side-effects on an internal API. - - `Variable`: Subclass of `Observable`, where you can modify the value as well. +The framework provides three classes `Observable`, `PublishSubject` and `Variable`: + + - `Observable`: An observable sequence that you can subscribe to, but not change the underlying value (immutable). This is useful to avoid side-effects on an internal API. + - `PublishSubject`: Subclass of `Observable`, that starts empty and only emits new elements to subscribers (mutable). + - `Variable`: Subclass of `Observable`, that starts with an initial value and replays it or the latest element to new subscribers (mutable). + +#### – Create and update a `PublishSubject` +A `PublishSubject` starts empty and only emits new elements to subscribers. -Using the given approach, your view-model could look like this: ```swift -class TimeViewModel { - // MARK: - Public properties - - /// The current time as a formatted string (**immutable**). - var formattedTime: Observable { - return formattedTimeSubject.asObservable - } - - // MARK: - Private properties - - /// The current time as a formatted string (**mutable**). - private let formattedTimeSubject: Variable = Variable("") - - private var timer: Timer? - - // MARK: - Initializer - - init() { - // Update variable with current time every second. - timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] _ in - self?.formattedTimeSubject.value = "\(Date())" - }) - } -``` - -And your view controller like this: -```swift -class TimeViewController: UIViewController { - // MARK: - Outlets - - @IBOutlet private var timeLabel: UILabel! - - // MARK: - Private properties - - /// The view model calculating the current time. - private let timeViewModel = TimeViewModel() - - /// The dispose bag for this view controller. On it's deallocation, it removes the - /// subscribtion-closures from the corresponding observable-properties. - private var disposeBag = DisposeBag() - - // MARK: - Public methods - - override func viewDidLoad() { - super.viewDidLoad() - - timeViewModel.formattedTime.subscribe { [weak self] newFormattedTime, _ in - self?.timeLabel.text = newFormattedTime - }.disposed(by: &disposeBag) - } -``` - -Feel free to check out the example application for a better understanding of this approach 🙂 - -#### Further details - -#### – Create and update variable -```swift -let formattedTimeSubject = Variable("") +let userLocationSubject = PublishSubject() // ... -formattedTimeSubject.value = "4:20 PM" +userLocationSubject.update(receivedUserLocation) ``` -#### – Create an observable -Initializing an observable directly is not possible, as this would lead to a sequence that will never change. Instead, use the computed property `asObservable` from `Variable` to cast the instance to an observable. +#### – Create and update a `Variable` +A `Variable` starts with an initial value and replays it or the latest element to new subscribers. + +```swift +let formattedTimeSubject = Variable("4:20 PM") + +// ... + +formattedTimeSubject.value = "4:21 PM" +``` + +#### – Create an `Observable` +Initializing an observable directly is not possible, as this would lead to a sequence that will never change. Instead you need to cast a `PublishSubject` or a `Variable` to an observable. + ```swift var formattedTime: Observable { - return formattedTimeSubject.asObservable + formattedTimeSubject } ``` +```swift +lazy var formattedTime: Observable = formattedTimeSubject +``` #### – Subscribe to changes -Every subscriber gets initialized with the current value and updated on all further changes to the observable value. +A subscriber will be informed at different times, depending on the subclass of the observable: + + - `PublishSubject`: Starts empty and only emits new elements to subscribers. + - `Variable`: Starts with an initial value and replays it or the latest element to new subscribers. + +To subscribe to an observable, you need to use the method `func subscribe(_ observer: @escaping Observer) -> Disposable`. ```swift formattedTime.subscribe { [weak self] newFormattedTime, oldFormattedTime in @@ -141,7 +115,7 @@ Please notice that the old value (`oldFormattedTime`) is an optional of the unde When you subscribe to an `Observable` the method returns a `Disposable`, which is basically a reference to the new subscription. -We need to maintain it, in order to properly control the lifecycle of that subscription. +We need to maintain it, in order to properly control the life-cycle of that subscription. Let me explain you why in a little example: @@ -154,6 +128,7 @@ Let me explain you why in a little example: > As a workaround, we store the returned disposable from the subscription on the view-model. On deallocation of the disposable, it automatically informs the observable property to remove the referenced subscription closure. In case you only use a single subscriber you can store the returned `Disposable` to a variable: + ```swift let disposable = formattedTime.subscribe { [weak self] newFormattedTime, oldFormattedTime in // ... @@ -161,6 +136,7 @@ let disposable = formattedTime.subscribe { [weak self] newFormattedTime, oldForm ``` In case you're having multiple observers, you can store all returned `Disposable` in an array of `Disposable`. (To match the syntax from [RxSwift](https://github.com/ReactiveX/RxSwift), this pod contains a typealias called `DisposeBag`, which is an array of `Disposable`). + ```swift var disposeBag = DisposeBag() @@ -176,7 +152,8 @@ formattedDate.subscribe { [weak self] newFormattedDate, oldFormattedDate in A `DisposeBag` is exactly what it says it is, a bag (or array) of disposables. #### – Observing `Equatable` values -If you create an Observable which underlying type conforms to `Equtable` you can subscribe to changes using a specific filter. Therefore this pod contains the method: +If you create an Observable which underlying type conforms to `Equatable` you can subscribe to changes using a specific filter. Therefore this pod contains the method: + ```swift typealias Filter = (NewValue, OldValue) -> Bool @@ -188,14 +165,81 @@ Using this method, the observer will only be notified on changes if the correspo This pod comes with one predefined filter method, called `subscribeDistinct`. Subscribing to an observable using this method, will only notify the observer if the new value is different from the old value. This is useful to prevent unnecessary UI-Updates. Feel free to add more filters, by extending the `Observable` like this: + ```swift extension Observable where T: Equatable {} ``` -### Author +#### – Getting the current value synchronously +You can get the current value of the `Observable` by accessing the property `value`. However it is always better to subscribe to a given observable! This **shortcut** should only be used during **testing**. + +```swift +XCTAssertEqual(viewModel.formattedTime.value, "4:20") +``` + +### Sample code +Using the given approach, your view-model could look like this: + +```swift +class TimeViewModel { + // MARK: - Public properties + + /// The current time as a formatted string (**immutable**). + var formattedTime: Observable { + formattedTimeSubject + } + + // MARK: - Private properties + + /// The current time as a formatted string (**mutable**). + private let formattedTimeSubject: Variable = Variable("\(Date())") + + private var timer: Timer? + + // MARK: - Initializer + + init() { + // Update variable with current time every second. + timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] _ in + self?.formattedTimeSubject.value = "\(Date())" + }) + } +``` + +And your view controller like this: + +```swift +class TimeViewController: UIViewController { + // MARK: - Outlets + + @IBOutlet private var timeLabel: UILabel! + + // MARK: - Private properties + + /// The view model calculating the current time. + private let timeViewModel = TimeViewModel() + + /// The dispose bag for this view controller. On it's deallocation, it removes the + /// subscription-closures from the corresponding observable-properties. + private var disposeBag = DisposeBag() + + // MARK: - Public methods + + override func viewDidLoad() { + super.viewDidLoad() + + timeViewModel.formattedTime.subscribe { [weak self] newFormattedTime, _ in + self?.timeLabel.text = newFormattedTime + }.disposed(by: &disposeBag) + } +``` +Feel free to check out the example application as well for a better understanding of this approach 🙂 + + +### Author Felix Mau (me(@)felix.hamburg) -### License +### License LightweightObservable is available under the MIT license. See the LICENSE file for more info. diff --git a/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json b/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json index 8ca9c23..4e741da 100644 --- a/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json +++ b/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json @@ -24,7 +24,7 @@ "source_files": "GradientLoadingBar/Classes/**/*", "dependencies": { "LightweightObservable": [ - "~> 1.0" + "~> 2.0" ] }, "swift_version": "5.0" diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index 01157f8..15d5b83 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -1,10 +1,10 @@ PODS: - GradientLoadingBar (2.0.1): - - LightweightObservable (~> 1.0) - - LightweightObservable (1.0.3) + - LightweightObservable (~> 2.0) + - LightweightObservable (2.0.0) - SnapshotTesting (1.6.0) - - SwiftFormat/CLI (0.40.13) - - SwiftLint (0.36.0) + - SwiftFormat/CLI (0.41.2) + - SwiftLint (0.37.0) DEPENDENCIES: - GradientLoadingBar (from `../`) @@ -24,11 +24,11 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - GradientLoadingBar: 4ef091b906199ffe5cec36f51aa45953d9b3e69e - LightweightObservable: 8687e8e1e2940ae2f64d7f71fe78c036d89c966f + GradientLoadingBar: f9e97f00d11c16021c2b232a9799544c3429a146 + LightweightObservable: f0c032384379a17cb048b861e33de8209155d7be SnapshotTesting: 9f478335073a830eafb7dc1fcd526c5e90143991 - SwiftFormat: d548b3585a6dbe64390177b386e95375b8c300b6 - SwiftLint: fc9859e4e1752340664851f667bb1898b9c90114 + SwiftFormat: 09921e624a7c5c53a687a9ae625fee48071a5d71 + SwiftLint: c078a14d7d7ade75e5507795d185e3da41d844d2 PODFILE CHECKSUM: f56a08d884831d712155be32578b7364270d0af0 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 0bfbcdf..8cf1a98 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -30,7 +30,8 @@ /* Begin PBXBuildFile section */ 0A8B8C10EEE41F7A0B243CFD690CDA60 /* Snapshotting.swift in Sources */ = {isa = PBXBuildFile; fileRef = D024359A1D7FCB26F8230048CBE40245 /* Snapshotting.swift */; }; 0C6AB859A1656DE69158A16278238D55 /* URLRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566491AD1D2F09BEE83815EF1EC5C5E /* URLRequest.swift */; }; - 0DAED264381366A2E84119677C6F6DCB /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF2550296A552984B5E78D433C4F78F9 /* Disposable.swift */; }; + 0DAED264381366A2E84119677C6F6DCB /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FD3FE89DCA76B16901DEB74B192C425 /* Disposable.swift */; }; + 17638B38223AAF22D7B211867EFDEADC /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FC3284BBD34713A3AB3C06B372588DF /* Observable.swift */; }; 1AB5DB926319ED83D108A7029C3CE863 /* GradientActivityIndicatorView+AnimateIsHidden.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CB4951B606B02B2484B9451FAEC183C /* GradientActivityIndicatorView+AnimateIsHidden.swift */; }; 1DD89710BCCBDEAA28A498BC74B1E2F1 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4933D3705B8DF51EBD769933097734B /* String.swift */; }; 231C9E52DF5D5C18E4ABF8E50BBB1D21 /* SnapshotTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE9A75C2A2CEA21E5945F499608F6113 /* SnapshotTestCase.swift */; }; @@ -38,8 +39,7 @@ 23ED8630B019A004BC2A54C98AB1399C /* Pods-GradientLoadingBar_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8194C4CB9E683FC366F48513ED1B1A9A /* Pods-GradientLoadingBar_Example-dummy.m */; }; 2A7E059B2E978382CFA30F2A3BB6D2C5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E59CE2F9522AE21F97AA29799051F00E /* Foundation.framework */; }; 3123B111C91B4E80CF939ACAA86317A4 /* CALayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6CB418AC0911177C9A2C28E35D1612C /* CALayer.swift */; }; - 3191DAE3BD6A98ED72A58C2A321A2CBE /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A710AFD738829E3B8F094FB6F52FDE9B /* Observable.swift */; }; - 422BE8280621D3716ED46A427310D5D1 /* Observable+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF318454F91378313461D7C8444A2D69 /* Observable+Equatable.swift */; }; + 44A9CDE2D522E447FC0887D67AD6C94D /* Observable+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB38C0900086F6224F07ECDADA306EC4 /* Observable+Equatable.swift */; }; 46C1549B816BBA0D22AEC7860C5D99C7 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0965FCF94C6751E5F873995C0CC05032 /* XCTest.framework */; }; 4A53946B8515FB1817A70D133E62A27E /* LightweightObservable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 834918404C77B6D44D53C01B3D12C581 /* LightweightObservable.framework */; }; 4B5A5EBA97A912894C10D040B5A1225D /* Pods-GradientLoadingBar_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 132C18988D60EF85736C043D43C19E57 /* Pods-GradientLoadingBar_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -68,12 +68,12 @@ B25E5B67C110AC032DF1D9E03AD1E16D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E59CE2F9522AE21F97AA29799051F00E /* Foundation.framework */; }; B5A32B041128C7DD110CDBDA0B06806E /* AssertSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F6EC1196F8E290039A6428E4A44356E /* AssertSnapshot.swift */; }; B8D288501F35D6826557E0ED76172B54 /* PlistEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7AD7A76B30313A242F01C70F6BEBF90 /* PlistEncoder.swift */; }; - BAE545730096FD246A85F92769270B23 /* LightweightObservable-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7C57B3850F023AC144E8187AEBEE75 /* LightweightObservable-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BAE545730096FD246A85F92769270B23 /* LightweightObservable-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8811E9B8E468EC5DF980E42E095FF9DF /* LightweightObservable-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC1EF05A1DCF0FA9FB6A10480A449138 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 661E1BC648C05340EADD4E73E4933993 /* Async.swift */; }; CE8387F85FA7B1C55704E5BDD58C9F17 /* GradientLoadingBarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BCAE0CD3437194563898E5D3689C0C /* GradientLoadingBarViewModel.swift */; }; D0A80857A56FB7F811A975C4882C64AD /* CaseIterable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C4B92D0A10F2BCF45454A91AACA118 /* CaseIterable.swift */; }; D252C07D5F4521EA7DBAF84AC4A1BFC0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E59CE2F9522AE21F97AA29799051F00E /* Foundation.framework */; }; - D429373DA9F337AEEFE4B5828482799F /* LightweightObservable-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 14D3A641892244027B3835C0AAE13F3D /* LightweightObservable-dummy.m */; }; + D429373DA9F337AEEFE4B5828482799F /* LightweightObservable-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DEEBFD86E62974E91E942A621C64BC1 /* LightweightObservable-dummy.m */; }; DC82754FF0AA19CEEF707C55CBB24008 /* GradientActivityIndicatorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53527D1C0CB9BB59CCA8EE08A62C2224 /* GradientActivityIndicatorViewModel.swift */; }; DDF84D301E919F39F3E9572FB8DBF03E /* SnapshotTesting-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CD50BFDCF4981DDB3C936492239658C2 /* SnapshotTesting-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; DE237C23FCFE8A5FC662FD5AC0BBDE1B /* Internal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3C50D35B00945DD26828798F19D20C /* Internal.swift */; }; @@ -148,15 +148,14 @@ /* Begin PBXFileReference section */ 06BCAE0CD3437194563898E5D3689C0C /* GradientLoadingBarViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModel.swift; sourceTree = ""; }; - 06E8ED304B6DC5EEA9733DF0B1EC830B /* LightweightObservable-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "LightweightObservable-Info.plist"; sourceTree = ""; }; 0965FCF94C6751E5F873995C0CC05032 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 0FC3284BBD34713A3AB3C06B372588DF /* Observable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Observable.swift; path = LightweightObservable/Classes/Observable.swift; sourceTree = ""; }; 108AACC96F7DBC089B0840E09F19C698 /* Pods-GradientLoadingBar_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Example.release.xcconfig"; sourceTree = ""; }; 11D94A25CBB2F8B53BC2ADA080BC09FE /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; 12A083D7F47F281A3A24E2E246151F93 /* GradientLoadingBar.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = GradientLoadingBar.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 132C18988D60EF85736C043D43C19E57 /* Pods-GradientLoadingBar_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GradientLoadingBar_Tests-umbrella.h"; sourceTree = ""; }; 13520AB8B3790CE3CEDCBBEEE1EF237A /* Pods_GradientLoadingBar_SnapshotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_GradientLoadingBar_SnapshotTests.framework; path = "Pods-GradientLoadingBar_SnapshotTests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 144334A6907A0BC204CF178F6B42C78C /* XCTAttachment.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XCTAttachment.swift; path = Sources/SnapshotTesting/Common/XCTAttachment.swift; sourceTree = ""; }; - 14D3A641892244027B3835C0AAE13F3D /* LightweightObservable-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LightweightObservable-dummy.m"; sourceTree = ""; }; 1541E22840B0A04DC99936F3875E49D3 /* UIImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIImage.swift; path = Sources/SnapshotTesting/Snapshotting/UIImage.swift; sourceTree = ""; }; 1679A4CF92D4ADFB15F8200201EC3AE5 /* Pods-GradientLoadingBar_SnapshotTests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GradientLoadingBar_SnapshotTests-frameworks.sh"; sourceTree = ""; }; 1711FC18263D47D46851F0433A93F110 /* Pods_GradientLoadingBar_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_GradientLoadingBar_Tests.framework; path = "Pods-GradientLoadingBar_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -167,26 +166,27 @@ 1BE0B5721F553E22547D9A94E12DD03F /* SnapshotTesting.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapshotTesting.xcconfig; sourceTree = ""; }; 1CA5ADE67427DB590BC5414E8E4498BA /* Pods-GradientLoadingBar_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GradientLoadingBar_Tests-acknowledgements.plist"; sourceTree = ""; }; 1CB4951B606B02B2484B9451FAEC183C /* GradientActivityIndicatorView+AnimateIsHidden.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "GradientActivityIndicatorView+AnimateIsHidden.swift"; sourceTree = ""; }; + 1DEEBFD86E62974E91E942A621C64BC1 /* LightweightObservable-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LightweightObservable-dummy.m"; sourceTree = ""; }; 1EA2E5A34FC1B7CFF331B89A444CFF9F /* SceneKit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SceneKit.swift; path = Sources/SnapshotTesting/Snapshotting/SceneKit.swift; sourceTree = ""; }; - 211933270108A13674AB94E0E3BC98D2 /* LightweightObservable.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LightweightObservable.xcconfig; sourceTree = ""; }; 219D91F90F2D4E48019FF8920700C17F /* Pods-GradientLoadingBar_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-GradientLoadingBar_Tests-acknowledgements.markdown"; sourceTree = ""; }; + 220539AEEC34898FA7E63555641B5663 /* LightweightObservable-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LightweightObservable-prefix.pch"; sourceTree = ""; }; 269E84D7ECD34A5AB94A824528F12271 /* NSView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSView.swift; path = Sources/SnapshotTesting/Snapshotting/NSView.swift; sourceTree = ""; }; 2D246858B1E28690CC1921F1EC8328E1 /* Pods-GradientLoadingBar_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GradientLoadingBar_Example-frameworks.sh"; sourceTree = ""; }; 2E16A843354D5BC8D4DA54D9AEFEAAB2 /* Pods-GradientLoadingBar_SnapshotTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GradientLoadingBar_SnapshotTests-acknowledgements.plist"; sourceTree = ""; }; + 334E65EE8E60507426A496CE2380D0DB /* LightweightObservable.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LightweightObservable.xcconfig; sourceTree = ""; }; 349852370D1AB476FD5FA4B23F1404F9 /* GradientLoadingBar-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GradientLoadingBar-prefix.pch"; sourceTree = ""; }; - 34D114D0B51C3EAD5CA081C7D2BFFF2A /* LightweightObservable.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = LightweightObservable.modulemap; sourceTree = ""; }; 37AC0455B865BC1335745F27A7180B3F /* SnapshotTesting-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapshotTesting-prefix.pch"; sourceTree = ""; }; 38FD9B2F414E880C3CD726916B00C935 /* Codable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Codable.swift; path = Sources/SnapshotTesting/Snapshotting/Codable.swift; sourceTree = ""; }; 3A3C50D35B00945DD26828798F19D20C /* Internal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Internal.swift; path = Sources/SnapshotTesting/Common/Internal.swift; sourceTree = ""; }; 3A900E1CFF1D76CF61DDF7358F5C8863 /* Pods-GradientLoadingBar_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GradientLoadingBar_Example-umbrella.h"; sourceTree = ""; }; 3C6A379C135C84644F189B8056CCBA04 /* Pods_GradientLoadingBar_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_GradientLoadingBar_Example.framework; path = "Pods-GradientLoadingBar_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3FD3FE89DCA76B16901DEB74B192C425 /* Disposable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Disposable.swift; path = LightweightObservable/Classes/Disposable.swift; sourceTree = ""; }; 4133F785EFF39E5F2420EEC0D952E042 /* SnapshotTesting-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SnapshotTesting-dummy.m"; sourceTree = ""; }; 4283AD1FDC393BDF3385FDEB6295B439 /* GradientLoadingBar-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GradientLoadingBar-dummy.m"; sourceTree = ""; }; 4371A74F9A6D74628527A30E755EFF25 /* Pods-GradientLoadingBar_SnapshotTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GradientLoadingBar_SnapshotTests-umbrella.h"; sourceTree = ""; }; 4BF1AE548385A7B7B7218C679A29A834 /* UIView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIView.swift; path = Sources/SnapshotTesting/Snapshotting/UIView.swift; sourceTree = ""; }; 53527D1C0CB9BB59CCA8EE08A62C2224 /* GradientActivityIndicatorViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GradientActivityIndicatorViewModel.swift; sourceTree = ""; }; 652D9AA358DBDB2DBA1CFB02CCBA8DC4 /* Pods-GradientLoadingBar_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GradientLoadingBar_Tests-Info.plist"; sourceTree = ""; }; - 656794E903F00F08A79611B559471CD8 /* LightweightObservable-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LightweightObservable-prefix.pch"; sourceTree = ""; }; 6586E9DC77F13E27590E444324A36C47 /* Constants.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 661E1BC648C05340EADD4E73E4933993 /* Async.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Async.swift; path = Sources/SnapshotTesting/Async.swift; sourceTree = ""; }; 67873E92210DD4E777C49C6E8AEDC108 /* GradientLoadingBar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GradientLoadingBar.framework; path = GradientLoadingBar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -195,10 +195,12 @@ 6DDA6FB19B0D9F0690352027FE76771A /* GradientLoadingBarController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GradientLoadingBarController.swift; path = GradientLoadingBar/Classes/GradientLoadingBarController.swift; sourceTree = ""; }; 6F7448547AB63D7FE246FFD2F35598E0 /* UIViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIViewController.swift; path = Sources/SnapshotTesting/Snapshotting/UIViewController.swift; sourceTree = ""; }; 73DF3D7BD316EDAA8BE47C2708C98323 /* GradientLoadingBar.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GradientLoadingBar.modulemap; sourceTree = ""; }; + 75BFE8FD604A1FFAA60CEED94A1F13C4 /* LightweightObservable-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "LightweightObservable-Info.plist"; sourceTree = ""; }; 7D20C44E8C1353812EF9D6DE25B423AA /* GradientLoadingBar-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GradientLoadingBar-umbrella.h"; sourceTree = ""; }; 8194C4CB9E683FC366F48513ED1B1A9A /* Pods-GradientLoadingBar_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-GradientLoadingBar_Example-dummy.m"; sourceTree = ""; }; 834918404C77B6D44D53C01B3D12C581 /* LightweightObservable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LightweightObservable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 85C51127E8FCAD347B6959BE176A7FAE /* SnapshotTesting-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SnapshotTesting-Info.plist"; sourceTree = ""; }; + 8811E9B8E468EC5DF980E42E095FF9DF /* LightweightObservable-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LightweightObservable-umbrella.h"; sourceTree = ""; }; 8F6EC1196F8E290039A6428E4A44356E /* AssertSnapshot.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssertSnapshot.swift; path = Sources/SnapshotTesting/AssertSnapshot.swift; sourceTree = ""; }; 90FFED11EFBD01CF65BD4AAB92DD02DB /* GradientActivityIndicatorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GradientActivityIndicatorView.swift; sourceTree = ""; }; 916C6ECE7711438EBAA91857D356E1B7 /* SwiftFormat.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftFormat.xcconfig; sourceTree = ""; }; @@ -214,9 +216,8 @@ A4670DF6ADBDF1CD1175DD92AADA3089 /* GradientLoadingBar.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GradientLoadingBar.xcconfig; sourceTree = ""; }; A4933D3705B8DF51EBD769933097734B /* String.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = String.swift; path = Sources/SnapshotTesting/Snapshotting/String.swift; sourceTree = ""; }; A652F20CE7EE44E64565C2120B651665 /* Pods-GradientLoadingBar_SnapshotTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-GradientLoadingBar_SnapshotTests.modulemap"; sourceTree = ""; }; - A710AFD738829E3B8F094FB6F52FDE9B /* Observable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Observable.swift; path = LightweightObservable/Classes/Observable/Observable.swift; sourceTree = ""; }; + A687FABFA8DA9112CE64F9BA78124696 /* LightweightObservable.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = LightweightObservable.modulemap; sourceTree = ""; }; A95E7032DE35DF972EF7FEC8A884303B /* Pods-GradientLoadingBar_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Example.debug.xcconfig"; sourceTree = ""; }; - AC7C57B3850F023AC144E8187AEBEE75 /* LightweightObservable-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LightweightObservable-umbrella.h"; sourceTree = ""; }; B12A8C84D679379006ADE9E1F57F8803 /* NSViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSViewController.swift; path = Sources/SnapshotTesting/Snapshotting/NSViewController.swift; sourceTree = ""; }; B1518F0564D9405495037F4713C4F143 /* Pods-GradientLoadingBar_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-GradientLoadingBar_Tests.modulemap"; sourceTree = ""; }; B27AAA41B1DEF56C8059867126A15A38 /* Pods-GradientLoadingBar_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GradientLoadingBar_Example-Info.plist"; sourceTree = ""; }; @@ -232,8 +233,8 @@ E0D90990792D653F523A884442305989 /* Pods-GradientLoadingBar_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-GradientLoadingBar_Example.modulemap"; sourceTree = ""; }; E59CE2F9522AE21F97AA29799051F00E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; E94DC28C03CC14E19767737B588D8D43 /* readme.md */ = {isa = PBXFileReference; includeInIndex = 1; path = readme.md; sourceTree = ""; }; + EB38C0900086F6224F07ECDADA306EC4 /* Observable+Equatable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Observable+Equatable.swift"; path = "LightweightObservable/Classes/Extensions/Observable+Equatable.swift"; sourceTree = ""; }; EE9F9ED5350FB7B00008AA447329D95A /* Description.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Description.swift; path = Sources/SnapshotTesting/Snapshotting/Description.swift; sourceTree = ""; }; - EF318454F91378313461D7C8444A2D69 /* Observable+Equatable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Observable+Equatable.swift"; path = "LightweightObservable/Classes/Observable/Observable+Equatable.swift"; sourceTree = ""; }; F142A9A722ECB4B932EEEEA9B4402217 /* SpriteKit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SpriteKit.swift; path = Sources/SnapshotTesting/Snapshotting/SpriteKit.swift; sourceTree = ""; }; F196AAA163469B17170E99B82C7C4C0A /* LightweightObservable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = LightweightObservable.framework; path = LightweightObservable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F7B1750DE470F045803DE2094D5F7264 /* Pods-GradientLoadingBar_SnapshotTests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GradientLoadingBar_SnapshotTests-Info.plist"; sourceTree = ""; }; @@ -242,7 +243,6 @@ FE9A75C2A2CEA21E5945F499608F6113 /* SnapshotTestCase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SnapshotTestCase.swift; path = Sources/SnapshotTesting/SnapshotTestCase.swift; sourceTree = ""; }; FEC6E4FE123FE19B3057E543191152D5 /* SnapshotTesting.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SnapshotTesting.modulemap; sourceTree = ""; }; FF135E1D23F08BE7F1D7FFC86260EF9B /* Pods-GradientLoadingBar_SnapshotTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-GradientLoadingBar_SnapshotTests-acknowledgements.markdown"; sourceTree = ""; }; - FF2550296A552984B5E78D433C4F78F9 /* Disposable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Disposable.swift; path = LightweightObservable/Classes/Disposable.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -315,6 +315,18 @@ path = "Target Support Files/Pods-GradientLoadingBar_Tests"; sourceTree = ""; }; + 42CF48FE0CF02BFB18B0BFDE656771A4 /* LightweightObservable */ = { + isa = PBXGroup; + children = ( + 3FD3FE89DCA76B16901DEB74B192C425 /* Disposable.swift */, + 0FC3284BBD34713A3AB3C06B372588DF /* Observable.swift */, + EB38C0900086F6224F07ECDADA306EC4 /* Observable+Equatable.swift */, + 43B203DF94D079773CE2576CEB2FE825 /* Support Files */, + ); + name = LightweightObservable; + path = LightweightObservable; + sourceTree = ""; + }; 4317A23E57A79F487E9EEE81F747B8BE /* SwiftLint */ = { isa = PBXGroup; children = ( @@ -337,6 +349,20 @@ name = Products; sourceTree = ""; }; + 43B203DF94D079773CE2576CEB2FE825 /* Support Files */ = { + isa = PBXGroup; + children = ( + A687FABFA8DA9112CE64F9BA78124696 /* LightweightObservable.modulemap */, + 334E65EE8E60507426A496CE2380D0DB /* LightweightObservable.xcconfig */, + 1DEEBFD86E62974E91E942A621C64BC1 /* LightweightObservable-dummy.m */, + 75BFE8FD604A1FFAA60CEED94A1F13C4 /* LightweightObservable-Info.plist */, + 220539AEEC34898FA7E63555641B5663 /* LightweightObservable-prefix.pch */, + 8811E9B8E468EC5DF980E42E095FF9DF /* LightweightObservable-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/LightweightObservable"; + sourceTree = ""; + }; 46BA5AF059FB6D85D0750DCC6A96ADEF /* Misc */ = { isa = PBXGroup; children = ( @@ -376,7 +402,7 @@ 61DC97DF4B43FDAE192E35D2A1E8E9DF /* Pods */ = { isa = PBXGroup; children = ( - CC42008C0EA9236DE550F48BF3C4D07C /* LightweightObservable */, + 42CF48FE0CF02BFB18B0BFDE656771A4 /* LightweightObservable */, 71636720CA4DD408F2B602341B0E133D /* SnapshotTesting */, 9FE463918895C7B587CE7D7509F7AF55 /* SwiftFormat */, 4317A23E57A79F487E9EEE81F747B8BE /* SwiftLint */, @@ -487,20 +513,6 @@ name = iOS; sourceTree = ""; }; - BECC4BF10A25D3EC0C02B11535F8B8BC /* Support Files */ = { - isa = PBXGroup; - children = ( - 34D114D0B51C3EAD5CA081C7D2BFFF2A /* LightweightObservable.modulemap */, - 211933270108A13674AB94E0E3BC98D2 /* LightweightObservable.xcconfig */, - 14D3A641892244027B3835C0AAE13F3D /* LightweightObservable-dummy.m */, - 06E8ED304B6DC5EEA9733DF0B1EC830B /* LightweightObservable-Info.plist */, - 656794E903F00F08A79611B559471CD8 /* LightweightObservable-prefix.pch */, - AC7C57B3850F023AC144E8187AEBEE75 /* LightweightObservable-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/LightweightObservable"; - sourceTree = ""; - }; CAC0E7E2279CD0610FD02BBA5E397CDB /* Support Files */ = { isa = PBXGroup; children = ( @@ -510,18 +522,6 @@ path = "../Target Support Files/SwiftFormat"; sourceTree = ""; }; - CC42008C0EA9236DE550F48BF3C4D07C /* LightweightObservable */ = { - isa = PBXGroup; - children = ( - FF2550296A552984B5E78D433C4F78F9 /* Disposable.swift */, - A710AFD738829E3B8F094FB6F52FDE9B /* Observable.swift */, - EF318454F91378313461D7C8444A2D69 /* Observable+Equatable.swift */, - BECC4BF10A25D3EC0C02B11535F8B8BC /* Support Files */, - ); - name = LightweightObservable; - path = LightweightObservable; - sourceTree = ""; - }; CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( @@ -857,8 +857,8 @@ files = ( 0DAED264381366A2E84119677C6F6DCB /* Disposable.swift in Sources */, D429373DA9F337AEEFE4B5828482799F /* LightweightObservable-dummy.m in Sources */, - 422BE8280621D3716ED46A427310D5D1 /* Observable+Equatable.swift in Sources */, - 3191DAE3BD6A98ED72A58C2A321A2CBE /* Observable.swift in Sources */, + 44A9CDE2D522E447FC0887D67AD6C94D /* Observable+Equatable.swift in Sources */, + 17638B38223AAF22D7B211867EFDEADC /* Observable.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1187,9 +1187,9 @@ }; name = Release; }; - 44121B9E0B97FBDCE8309C61186CD5C6 /* Debug */ = { + 4A1AA437DA57B1A8278C07CD0CD65DC8 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 211933270108A13674AB94E0E3BC98D2 /* LightweightObservable.xcconfig */; + baseConfigurationReference = 334E65EE8E60507426A496CE2380D0DB /* LightweightObservable.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CODE_SIGN_IDENTITY = ""; @@ -1212,12 +1212,13 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.1; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; 5A765DFB515CB0790B92CC49D624B6BD /* Debug */ = { isa = XCBuildConfiguration; @@ -1268,6 +1269,38 @@ }; name = Debug; }; + 7E8A79237CD57F0D31FF6F1CCE4C3E5E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 334E65EE8E60507426A496CE2380D0DB /* LightweightObservable.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/LightweightObservable/LightweightObservable-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/LightweightObservable/LightweightObservable-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/LightweightObservable/LightweightObservable.modulemap"; + PRODUCT_MODULE_NAME = LightweightObservable; + PRODUCT_NAME = LightweightObservable; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.1; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; 80E22FC8391D193F17430BF26FFFB242 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A95E7032DE35DF972EF7FEC8A884303B /* Pods-GradientLoadingBar_Example.debug.xcconfig */; @@ -1385,39 +1418,6 @@ }; name = Release; }; - CEA104522F9599FA6720675C3F005F1E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 211933270108A13674AB94E0E3BC98D2 /* LightweightObservable.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/LightweightObservable/LightweightObservable-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/LightweightObservable/LightweightObservable-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/LightweightObservable/LightweightObservable.modulemap"; - PRODUCT_MODULE_NAME = LightweightObservable; - PRODUCT_NAME = LightweightObservable; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; D391099D337E503BE258A73A274B5A0F /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 69838A921E83418B945E72EB342809F5 /* Pods-GradientLoadingBar_SnapshotTests.debug.xcconfig */; @@ -1634,8 +1634,8 @@ ADE518225F2C0914D89DC54CBE22013A /* Build configuration list for PBXNativeTarget "LightweightObservable" */ = { isa = XCConfigurationList; buildConfigurations = ( - 44121B9E0B97FBDCE8309C61186CD5C6 /* Debug */, - CEA104522F9599FA6720675C3F005F1E /* Release */, + 7E8A79237CD57F0D31FF6F1CCE4C3E5E /* Debug */, + 4A1AA437DA57B1A8278C07CD0CD65DC8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/Pods/SwiftFormat/CommandLineTool/swiftformat b/Example/Pods/SwiftFormat/CommandLineTool/swiftformat index 07b0158..318807c 100755 Binary files a/Example/Pods/SwiftFormat/CommandLineTool/swiftformat and b/Example/Pods/SwiftFormat/CommandLineTool/swiftformat differ diff --git a/Example/Pods/SwiftLint/swiftlint b/Example/Pods/SwiftLint/swiftlint index 11cd888..81abb96 100755 Binary files a/Example/Pods/SwiftLint/swiftlint and b/Example/Pods/SwiftLint/swiftlint differ diff --git a/Example/Pods/Target Support Files/LightweightObservable/LightweightObservable-Info.plist b/Example/Pods/Target Support Files/LightweightObservable/LightweightObservable-Info.plist index 10ad18b..0a12077 100644 --- a/Example/Pods/Target Support Files/LightweightObservable/LightweightObservable-Info.plist +++ b/Example/Pods/Target Support Files/LightweightObservable/LightweightObservable-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.3 + 2.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/Tests/ViewModel/GradientActivityIndicatorViewModelTestCase.swift b/Example/Tests/ViewModel/GradientActivityIndicatorViewModelTestCase.swift index b260874..1d9f9d0 100644 --- a/Example/Tests/ViewModel/GradientActivityIndicatorViewModelTestCase.swift +++ b/Example/Tests/ViewModel/GradientActivityIndicatorViewModelTestCase.swift @@ -43,8 +43,8 @@ class GradientActivityIndicatorViewModelTestCase: XCTestCase { XCTAssertEqual(viewModel.gradientLayerColors.value, expectedGradientLayerColors) } - func testInitializerShouldSetGradientLayerLocationsToCorrectValue() { - let receivedGradientLayerLocations = viewModel.gradientLayerLocations.value + func testInitializerShouldSetGradientLayerLocationsToCorrectValue() throws { + let receivedGradientLayerLocations = try XCTUnwrap(viewModel.gradientLayerLocations.value) let expectedGradientLayerLocations = makeGradientLocationAnimationMatrixInitialRow() // Unfortunately there is no easier way comparing an array of type `NSNumber` / `Double` with a given accuracy. diff --git a/GradientLoadingBar.podspec b/GradientLoadingBar.podspec index 3325ad9..47d3224 100644 --- a/GradientLoadingBar.podspec +++ b/GradientLoadingBar.podspec @@ -40,6 +40,6 @@ Inspired by https://codepen.io/marcobiedermann/pen/LExXWW # s.public_header_files = 'Pod/Classes/**/*.h' # s.frameworks = 'UIKit', 'MapKit' -s.dependency 'LightweightObservable', '~> 1.0' +s.dependency 'LightweightObservable', '~> 2.0' end diff --git a/GradientLoadingBar/Classes/ViewModel/GradientActivityIndicatorViewModel.swift b/GradientLoadingBar/Classes/ViewModel/GradientActivityIndicatorViewModel.swift index ef396b7..0f1b6ed 100644 --- a/GradientLoadingBar/Classes/ViewModel/GradientActivityIndicatorViewModel.swift +++ b/GradientLoadingBar/Classes/ViewModel/GradientActivityIndicatorViewModel.swift @@ -58,12 +58,12 @@ final class GradientActivityIndicatorViewModel { /// Observable color array for the gradient layer (of type `CGColor`). var gradientLayerColors: Observable<[CGColor]> { - gradientLayerColorsSubject.asObservable + gradientLayerColorsSubject } /// The (initial) color locations for the gradient layer. var gradientLayerLocations: Observable<[NSNumber]> { - gradientLayerLocationsSubject.asObservable + gradientLayerLocationsSubject } /// Color array used for the gradient (of type `UIColor`). @@ -158,7 +158,7 @@ final class GradientActivityIndicatorViewModel { /// ``` private func makeGradientLocationAnimationMatrixInitialRow() -> [NSNumber] { let gradientColorsQuantity = gradientColors.count - let gradientLayerColorsQuantity = gradientLayerColors.value.count + let gradientLayerColorsQuantity = gradientLayerColorsSubject.value.count let startLocationsQuantity = gradientLayerColorsQuantity - gradientColorsQuantity let startLocations = [NSNumber](repeating: 0.0, count: startLocationsQuantity) @@ -183,7 +183,7 @@ final class GradientActivityIndicatorViewModel { /// ``` private func makeGradientLocationAnimationMatrix() -> GradientLocationAnimationMatrix { let gradientColorsQuantity = gradientColors.count - let gradientLayerColorsQuantity = gradientLayerColors.value.count + let gradientLayerColorsQuantity = gradientLayerColorsSubject.value.count let gradientLocations = makeGradientLocations() diff --git a/GradientLoadingBar/Classes/ViewModel/GradientLoadingBarViewModel.swift b/GradientLoadingBar/Classes/ViewModel/GradientLoadingBarViewModel.swift index 3228494..74bfe30 100644 --- a/GradientLoadingBar/Classes/ViewModel/GradientLoadingBarViewModel.swift +++ b/GradientLoadingBar/Classes/ViewModel/GradientLoadingBarViewModel.swift @@ -16,7 +16,7 @@ final class GradientLoadingBarViewModel { /// Observable for the superview of the gradient-view. var superview: Observable { - return superviewSubject.asObservable + return superviewSubject } // MARK: - Private properties