diff --git a/Example/GradientLoadingBar.xcodeproj/project.pbxproj b/Example/GradientLoadingBar.xcodeproj/project.pbxproj index c01d04f..47cd642 100644 --- a/Example/GradientLoadingBar.xcodeproj/project.pbxproj +++ b/Example/GradientLoadingBar.xcodeproj/project.pbxproj @@ -12,16 +12,17 @@ 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; + 64E0F5BF2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */; }; + 64E0F5C02211B7D20066D00D /* DisposableTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5BD2211B7D20066D00D /* DisposableTestCase.swift */; }; + 64E0F5C12211B7D20066D00D /* ObservableTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5BE2211B7D20066D00D /* ObservableTestCase.swift */; }; 77357BD34CFF2778341F80E8 /* Pods_GradientLoadingBar_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03CD5D69D7C3FBBDBF5FABBB /* Pods_GradientLoadingBar_Example.framework */; }; 8020C040972E902A8CCAA9E7 /* Pods_GradientLoadingBar_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 434E3C8A6E245A38C2831E73 /* Pods_GradientLoadingBar_Tests.framework */; }; 972CFBCC2138849A006F14C9 /* SafeAreaExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972CFBCB2138849A006F14C9 /* SafeAreaExampleViewController.swift */; }; 97464E6721372BCD0097183A /* AdvancedExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97464E6621372BCD0097183A /* AdvancedExampleViewController.swift */; }; 97464E6921372C010097183A /* NavigationBarExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97464E6821372C010097183A /* NavigationBarExampleViewController.swift */; }; - 974E3F221FF2DEAA00C96A59 /* GradientLoadingBarViewModelTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 974E3F211FF2DEAA00C96A59 /* GradientLoadingBarViewModelTestCase.swift */; }; 97B6F5FE2143F31F008CFEA5 /* UIColor+CustomColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97B6F5FA2143F31F008CFEA5 /* UIColor+CustomColors.swift */; }; 97B6F5FF2143F31F008CFEA5 /* BlueFilledButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97B6F5FC2143F31F008CFEA5 /* BlueFilledButton.swift */; }; 97B6F6002143F31F008CFEA5 /* BlueBorderedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97B6F5FD2143F31F008CFEA5 /* BlueBorderedButton.swift */; }; - 97FA595B213184DF00CCD446 /* Observable+ObserveDistinctTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97FA595A213184DF00CCD446 /* Observable+ObserveDistinctTestCase.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,14 +51,15 @@ 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 607FACE51AFB9204008FA782 /* GradientLoadingBar_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GradientLoadingBar_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModelTestCase.swift; sourceTree = ""; }; + 64E0F5BD2211B7D20066D00D /* DisposableTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposableTestCase.swift; sourceTree = ""; }; + 64E0F5BE2211B7D20066D00D /* ObservableTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObservableTestCase.swift; sourceTree = ""; }; 972CFBCB2138849A006F14C9 /* SafeAreaExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeAreaExampleViewController.swift; sourceTree = ""; }; 97464E6621372BCD0097183A /* AdvancedExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedExampleViewController.swift; sourceTree = ""; }; 97464E6821372C010097183A /* NavigationBarExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarExampleViewController.swift; sourceTree = ""; }; - 974E3F211FF2DEAA00C96A59 /* GradientLoadingBarViewModelTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModelTestCase.swift; sourceTree = ""; }; 97B6F5FA2143F31F008CFEA5 /* UIColor+CustomColors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+CustomColors.swift"; sourceTree = ""; }; 97B6F5FC2143F31F008CFEA5 /* BlueFilledButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlueFilledButton.swift; sourceTree = ""; }; 97B6F5FD2143F31F008CFEA5 /* BlueBorderedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlueBorderedButton.swift; sourceTree = ""; }; - 97FA595A213184DF00CCD446 /* Observable+ObserveDistinctTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+ObserveDistinctTestCase.swift"; sourceTree = ""; }; C06CA4DFA1DCB931095ABD3D /* GradientLoadingBar.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = GradientLoadingBar.podspec; path = ../GradientLoadingBar.podspec; sourceTree = ""; }; F76834BE9E43CA11377EC030 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; FECB95A4857728345199461F /* Pods-GradientLoadingBar_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GradientLoadingBar_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.debug.xcconfig"; sourceTree = ""; }; @@ -134,9 +136,8 @@ 607FACE81AFB9204008FA782 /* Tests */ = { isa = PBXGroup; children = ( - 972B29D21F7F88F6009D9F89 /* Helpers */, + 64E0F5B92211B7D20066D00D /* Feature */, 607FACE91AFB9204008FA782 /* Supporting Files */, - 974E3F201FF2DE7A00C96A59 /* ViewModel */, ); path = Tests; sourceTree = ""; @@ -159,28 +160,30 @@ name = "Podspec Metadata"; sourceTree = ""; }; - 972B29D21F7F88F6009D9F89 /* Helpers */ = { + 64E0F5B92211B7D20066D00D /* Feature */ = { isa = PBXGroup; children = ( - 972B29D31F7F88F6009D9F89 /* Extensions */, + 64E0F5BA2211B7D20066D00D /* GradientLoadingBar */, + 64E0F5BC2211B7D20066D00D /* Observable */, ); - path = Helpers; + path = Feature; sourceTree = ""; }; - 972B29D31F7F88F6009D9F89 /* Extensions */ = { + 64E0F5BA2211B7D20066D00D /* GradientLoadingBar */ = { isa = PBXGroup; children = ( - 97FA595A213184DF00CCD446 /* Observable+ObserveDistinctTestCase.swift */, + 64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */, ); - path = Extensions; + path = GradientLoadingBar; sourceTree = ""; }; - 974E3F201FF2DE7A00C96A59 /* ViewModel */ = { + 64E0F5BC2211B7D20066D00D /* Observable */ = { isa = PBXGroup; children = ( - 974E3F211FF2DEAA00C96A59 /* GradientLoadingBarViewModelTestCase.swift */, + 64E0F5BD2211B7D20066D00D /* DisposableTestCase.swift */, + 64E0F5BE2211B7D20066D00D /* ObservableTestCase.swift */, ); - path = ViewModel; + path = Observable; sourceTree = ""; }; 97B6F5F92143F31F008CFEA5 /* Extensions */ = { @@ -352,12 +355,10 @@ inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-frameworks.sh", "${BUILT_PRODUCTS_DIR}/GradientLoadingBar/GradientLoadingBar.framework", - "${BUILT_PRODUCTS_DIR}/Observable/Observable.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GradientLoadingBar.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Observable.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -460,8 +461,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 974E3F221FF2DEAA00C96A59 /* GradientLoadingBarViewModelTestCase.swift in Sources */, - 97FA595B213184DF00CCD446 /* Observable+ObserveDistinctTestCase.swift in Sources */, + 64E0F5BF2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift in Sources */, + 64E0F5C02211B7D20066D00D /* DisposableTestCase.swift in Sources */, + 64E0F5C12211B7D20066D00D /* ObservableTestCase.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 3a9719f..2109701 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,9 +1,7 @@ PODS: - - GradientLoadingBar (1.1.14): - - Observable (~> 1.4) - - Observable (1.4.0) - - SwiftFormat/CLI (0.37.1) - - SwiftLint (0.29.2) + - GradientLoadingBar (1.1.14) + - SwiftFormat/CLI (0.39.0) + - SwiftLint (0.30.1) DEPENDENCIES: - GradientLoadingBar (from `../`) @@ -12,7 +10,6 @@ DEPENDENCIES: SPEC REPOS: https://github.com/cocoapods/specs.git: - - Observable - SwiftFormat - SwiftLint @@ -21,10 +18,9 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - GradientLoadingBar: b94404db4cce14c270eb6e5745f12bd93829c73c - Observable: 4b2ee25de74d007d57acdff801925e39f9613544 - SwiftFormat: 550bd718695b44b1f0cbb0185b8b713fa8c137ac - SwiftLint: 47df60bdea6e7e902b193b6596db8683aafd86a3 + GradientLoadingBar: 0a3864c14c36864de804b0c7e65045c713c32a9a + SwiftFormat: a27a799eeaf246313c3b388ad6d5ae33c78eb6f3 + SwiftLint: a54bf1fe12b55c68560eb2a7689dfc81458508f7 PODFILE CHECKSUM: 55891446b31c0884d45a4c65f1b52d307ff274bc diff --git a/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json b/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json index 2f9876e..19d4a07 100644 --- a/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json +++ b/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json @@ -20,10 +20,5 @@ "platforms": { "ios": "9.0" }, - "source_files": "GradientLoadingBar/Classes/**/*", - "dependencies": { - "Observable": [ - "~> 1.4" - ] - } + "source_files": "GradientLoadingBar/Classes/**/*" } diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index 3a9719f..2109701 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -1,9 +1,7 @@ PODS: - - GradientLoadingBar (1.1.14): - - Observable (~> 1.4) - - Observable (1.4.0) - - SwiftFormat/CLI (0.37.1) - - SwiftLint (0.29.2) + - GradientLoadingBar (1.1.14) + - SwiftFormat/CLI (0.39.0) + - SwiftLint (0.30.1) DEPENDENCIES: - GradientLoadingBar (from `../`) @@ -12,7 +10,6 @@ DEPENDENCIES: SPEC REPOS: https://github.com/cocoapods/specs.git: - - Observable - SwiftFormat - SwiftLint @@ -21,10 +18,9 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - GradientLoadingBar: b94404db4cce14c270eb6e5745f12bd93829c73c - Observable: 4b2ee25de74d007d57acdff801925e39f9613544 - SwiftFormat: 550bd718695b44b1f0cbb0185b8b713fa8c137ac - SwiftLint: 47df60bdea6e7e902b193b6596db8683aafd86a3 + GradientLoadingBar: 0a3864c14c36864de804b0c7e65045c713c32a9a + SwiftFormat: a27a799eeaf246313c3b388ad6d5ae33c78eb6f3 + SwiftLint: a54bf1fe12b55c68560eb2a7689dfc81458508f7 PODFILE CHECKSUM: 55891446b31c0884d45a4c65f1b52d307ff274bc diff --git a/Example/Pods/Observable/LICENSE b/Example/Pods/Observable/LICENSE deleted file mode 100644 index c5a8fd3..0000000 --- a/Example/Pods/Observable/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ - -MIT License - -Copyright (c) 2017 Robert-Hein Hooijmans - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/Example/Pods/Observable/Observable/Classes/Disposable.swift b/Example/Pods/Observable/Observable/Classes/Disposable.swift deleted file mode 100644 index 0367b7a..0000000 --- a/Example/Pods/Observable/Observable/Classes/Disposable.swift +++ /dev/null @@ -1,20 +0,0 @@ -import Foundation - -public typealias Disposal = [Disposable] - -public final class Disposable { - - private let dispose: () -> () - - init(_ dispose: @escaping () -> ()) { - self.dispose = dispose - } - - deinit { - dispose() - } - - public func add(to disposal: inout Disposal) { - disposal.append(self) - } -} diff --git a/Example/Pods/Observable/Observable/Classes/Lock.swift b/Example/Pods/Observable/Observable/Classes/Lock.swift deleted file mode 100644 index 4094474..0000000 --- a/Example/Pods/Observable/Observable/Classes/Lock.swift +++ /dev/null @@ -1,26 +0,0 @@ -import Foundation - -// https://cocoawithlove.com/blog/2016/06/02/threads-and-mutexes.html -// http://www.vadimbulavin.com/atomic-properties/ -// https://stackoverflow.com/a/47345863/976628 - -internal protocol Lock { - func lock() - func unlock() -} - -internal final class Mutex: Lock { - private var mutex: pthread_mutex_t = { - var mutex = pthread_mutex_t() - pthread_mutex_init(&mutex, nil) - return mutex - }() - - func lock() { - pthread_mutex_lock(&mutex) - } - - func unlock() { - pthread_mutex_unlock(&mutex) - } -} diff --git a/Example/Pods/Observable/Observable/Classes/Observable.swift b/Example/Pods/Observable/Observable/Classes/Observable.swift deleted file mode 100644 index 097a5d0..0000000 --- a/Example/Pods/Observable/Observable/Classes/Observable.swift +++ /dev/null @@ -1,68 +0,0 @@ -import Foundation - -public class ImmutableObservable { - - public typealias Observer = (T, T?) -> Void - - private var observers: [Int: (Observer, DispatchQueue?)] = [:] - private var uniqueID = (0...).makeIterator() - - fileprivate let lock: Lock = Mutex() - - fileprivate var _value: T { - didSet { - observers.values.forEach { observer, dispatchQueue in - - if let dispatchQueue = dispatchQueue { - dispatchQueue.async { - observer(self.value, oldValue) - } - } else { - observer(value, oldValue) - } - } - } - } - - public var value: T { - return _value - } - - public init(_ value: T) { - self._value = value - } - - public func observe(_ queue: DispatchQueue? = nil, _ observer: @escaping Observer) -> Disposable { - lock.lock() - defer { lock.unlock() } - - let id = uniqueID.next()! - - observers[id] = (observer, queue) - observer(value, nil) - - let disposable = Disposable { [weak self] in - self?.observers[id] = nil - } - - return disposable - } - - public func removeAllObservers() { - observers.removeAll() - } -} - -public class Observable: ImmutableObservable { - - public override var value: T { - get { - return _value - } - set { - lock.lock() - defer { lock.unlock() } - _value = newValue - } - } -} diff --git a/Example/Pods/Observable/README.md b/Example/Pods/Observable/README.md deleted file mode 100644 index 3bc40ea..0000000 --- a/Example/Pods/Observable/README.md +++ /dev/null @@ -1,88 +0,0 @@ -

- Observable -

- -**Observable** is the easiest way to observe values in Swift. - -## How to - -### Create an Observable - -```swift -var position = Observable(CGPoint.zero) -``` - -### Create Observer and ImmutableObserver - -```swift -var position = Observable(CGPoint.zero) -var immutablePosition: ImmutableObservable = position -// With an ImmutableObservable the value can't be changed, only read or observe it's value changes -``` - -### Add an observer - -```swift -position.observe { p in - // handle new position -} -``` - -### Add an observer and specify the DispatchQueue - -```swift -position.observe(DispatchQueue.main) { p in -// handle new position -} -``` - -### Change the value - -```swift -position.value = p -``` - -## Memory management - -For a single observer you can store the returned `Disposable` to a variable - -```swift -disposable = position.observe { p in - -``` - -For multiple observers you can add the disposable to a `Disposal` variable - -```swift -position.observe { }.add(to: &disposal) -``` - -And always weakify `self` when referencing `self` inside your observer - -```swift -position.observe { [weak self] position in -``` - -## Installation - -### CocoaPods - -**Observable** is available through [CocoaPods](http://cocoapods.org). To install -it, simply add the following line to your Podfile: - -```ruby -pod 'Observable' -``` - -### Carthage - -**Observable** is available through [Carthage](https://github.com/Carthage/Carthage). To install -it, simply add the following line to your Cartfile: - -```ruby -github "roberthein/Observable" "master" -``` - -## Suggestions or feedback? - -Feel free to create a pull request, open an issue or find [me on Twitter](https://twitter.com/roberthein). diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index a9d57eb..5f119c4 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,31 +7,25 @@ objects = { /* Begin PBXBuildFile section */ - 03F61FA0724C4C3A8DFE7939D7D0F1C5 /* UIView+AnimateIsHidden.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9976B0B1F9BDB6CB4E7204DBD1081B1 /* UIView+AnimateIsHidden.swift */; }; - 06C24252C63A62B4D962275EB05B9EA9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DF6AA5B777CE6872A2AC92643E0F757 /* Foundation.framework */; }; - 132267F3B4E9CA753A6BF27134FC5465 /* GradientLoadingBar-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E81C4CEB4E6A0793321B9591E1BD1B69 /* GradientLoadingBar-dummy.m */; }; - 13E8860F705BD1002D6164AD341B92FE /* Durations.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD3F66A317040A4DDA2612D78CE827DD /* Durations.swift */; }; - 166F1654BD9D0C8E3FD189C976E4DD8A /* Observable-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F09C3971033EB7D38DBDAA4976E7E9F4 /* Observable-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1B508C3732F51FCEB0F4635A802DADCA /* Pods-GradientLoadingBar_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B611CFC1F8EE4FAEC01581F75425F48F /* Pods-GradientLoadingBar_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 27B4FA1102726CB66B225E9DE43EC19C /* BottomGradientLoadingBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6494464C527430ED4F64A55E9ED0B8A4 /* BottomGradientLoadingBarController.swift */; }; - 34278664DAA67E936663F4E01FA8CDFC /* Observable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C47C72A5BD1CE40555C3CA440845A93E /* Observable.framework */; }; - 3D3EFA7D54862F41E53DFB5ACCE9D0D5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DF6AA5B777CE6872A2AC92643E0F757 /* Foundation.framework */; }; - 42C9B868EFF007C954640D7937E4D31F /* Pods-GradientLoadingBar_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EADFB0EFFF6A08CAA2D4588D6C2F0C44 /* Pods-GradientLoadingBar_Example-dummy.m */; }; - 49D1C6D426F426DAADCA0326273AAC42 /* GradientLoadingBar-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F7E205B5BAF8C6A9217862427737BBE /* GradientLoadingBar-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4D4B8228A9913829C00CF938E0C7C90E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DF6AA5B777CE6872A2AC92643E0F757 /* Foundation.framework */; }; - 52162FA2A406B07682707EC00E7960DF /* GradientLoadingBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 760501FE4A781A0A4A3BB4EE36D1E128 /* GradientLoadingBarController.swift */; }; - 59811596DEE4F2CF46FED33B8125FB07 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E083092CBF60F2715011C9F23574CEB /* Observable.swift */; }; + 17B6325C9E108764B460015F7191B83A /* GradientLoadingBar-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F7E205B5BAF8C6A9217862427737BBE /* GradientLoadingBar-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3CAA7A728F43E1EB82993F0868BBC0AF /* Pods-GradientLoadingBar_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EADFB0EFFF6A08CAA2D4588D6C2F0C44 /* Pods-GradientLoadingBar_Example-dummy.m */; }; + 4D4B8228A9913829C00CF938E0C7C90E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */; }; + 55AF16C7929CCE114DEBD48918B190AF /* GradientLoadingBar-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E81C4CEB4E6A0793321B9591E1BD1B69 /* GradientLoadingBar-dummy.m */; }; + 64E0F5B22211B6480066D00D /* GradientLoadingBarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5A82211B6480066D00D /* GradientLoadingBarViewModel.swift */; }; + 64E0F5B32211B6480066D00D /* GradientLoadingBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5A92211B6480066D00D /* GradientLoadingBarController.swift */; }; + 64E0F5B42211B6480066D00D /* BottomGradientLoadingBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5AA2211B6480066D00D /* BottomGradientLoadingBarController.swift */; }; + 64E0F5B52211B6480066D00D /* Durations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5AC2211B6480066D00D /* Durations.swift */; }; + 64E0F5B62211B6480066D00D /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5AE2211B6480066D00D /* GradientView.swift */; }; + 64E0F5B72211B6480066D00D /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5B02211B6480066D00D /* Disposable.swift */; }; + 64E0F5B82211B6480066D00D /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5B12211B6480066D00D /* Observable.swift */; }; + 6546432CC49E569B81E2DC4BC3C9A2CB /* UIColor+DefaultValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3929BC42FACCAFF16193DA16F07C92D /* UIColor+DefaultValues.swift */; }; + 69C76C33449FEBFF78BBDC94EE694EC5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */; }; 6B39B48E2A95E44666BAD8D7BAA2331E /* Pods-GradientLoadingBar_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BD04847FCD93EA8DB873ED60D7DAFE9 /* Pods-GradientLoadingBar_Tests-dummy.m */; }; - 7307623495DBF963E150BA3B5EEEC109 /* Observable-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BE4C26F419339AF6FEB407847B551DC /* Observable-dummy.m */; }; - 73B71B1D4D56F9B366CB5ACF26F15B88 /* UIColor+CustomColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FA583414819F76ADF5F59F2E667585C /* UIColor+CustomColors.swift */; }; - 87C19438979525BA0DBAA582FB6A5B12 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DF6AA5B777CE6872A2AC92643E0F757 /* Foundation.framework */; }; - 9F6FF95266983E325B01A3F72BECF50A /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9A49BCAE8F8EB569BE0321D71C6CF3 /* GradientView.swift */; }; - A5C8E5782BE408C3EEFF5037E768B616 /* ImmutableObservable+ObserveDistinct.swift in Sources */ = {isa = PBXBuildFile; fileRef = E624F41A654173DCD2381FB6014330B4 /* ImmutableObservable+ObserveDistinct.swift */; }; - AC929579BF66F38833EF4B5876165250 /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D12F26C7233A8F032B38D0A935E867C4 /* Disposable.swift */; }; + 7D1E168D6E79E03F2960CE51E513D634 /* UIColor+CustomColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FA583414819F76ADF5F59F2E667585C /* UIColor+CustomColors.swift */; }; + 9AAC7020094626B3D3716199EF579DB3 /* Pods-GradientLoadingBar_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B611CFC1F8EE4FAEC01581F75425F48F /* Pods-GradientLoadingBar_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A90FED5348717F4A397D32FEDF1C7EEB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */; }; + AA3F823EE392DA32CB961B91615BC96E /* UIView+AnimateIsHidden.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9976B0B1F9BDB6CB4E7204DBD1081B1 /* UIView+AnimateIsHidden.swift */; }; B104D6EEEB638E64FEDC3F17CF6CA7DA /* Pods-GradientLoadingBar_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 82F153091821DD341797CA12A8D4CAE1 /* Pods-GradientLoadingBar_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E2BF83D2ECC7B2674EF43F97BA433431 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9DFF1ABED118E9339435332DCDACDB /* Lock.swift */; }; - F182892639AF608EAABE0D4A0E6EBCE5 /* GradientLoadingBarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9396929A9EFCECCA67256186A0F92AB4 /* GradientLoadingBarViewModel.swift */; }; - FAFE554D7816324CC184B0DF6CC8BDD8 /* UIColor+DefaultValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3929BC42FACCAFF16193DA16F07C92D /* UIColor+DefaultValues.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -39,28 +33,14 @@ isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = C9E360AE7E621FF686F7C060178481D1; + remoteGlobalIDString = F66315F62F3F426F979FBA688C95BB49; remoteInfo = "Pods-GradientLoadingBar_Example"; }; - 11F0ABF401134D6A07D63CBB85302D0B /* PBXContainerItemProxy */ = { + 0A4C5EB7B411D126BCF5E8AEED59062F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = E6CCE0B41A1F307B9A6DBB1AB60162D3; - remoteInfo = Observable; - }; - 14097629F04F80655A04663B59127D8D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = E6CCE0B41A1F307B9A6DBB1AB60162D3; - remoteInfo = Observable; - }; - 9BBDC016F505E44F0E066512798A7A25 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8021F4FFF4A5140BF1448C374162E69D; + remoteGlobalIDString = B9D0FA9CCBF200478C7FA87EEDD00505; remoteInfo = GradientLoadingBar; }; /* End PBXContainerItemProxy section */ @@ -70,73 +50,62 @@ 1ACAE8D17B2522B64920E9EA81C13EBA /* Pods-GradientLoadingBar_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-GradientLoadingBar_Tests.modulemap"; sourceTree = ""; }; 1B20B670FBFC9008DFDE45D9D36A94BF /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1FAE2BD6B4E4E4C52D09F11474CCE982 /* GradientLoadingBar.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GradientLoadingBar.modulemap; sourceTree = ""; }; - 284E5B1E5B78675A430CFB3C83D79E8F /* Pods_GradientLoadingBar_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 29F34B3709A0B91080A953ED30B6C8F6 /* GradientLoadingBar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GradientLoadingBar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2BB9B4AFA01DC30399978F0AFE74FB96 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 2E9A49BCAE8F8EB569BE0321D71C6CF3 /* GradientView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; - 2F1BDD41157523D250EC77DD1B9034EE /* Observable-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Observable-prefix.pch"; sourceTree = ""; }; 2F7E205B5BAF8C6A9217862427737BBE /* GradientLoadingBar-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GradientLoadingBar-umbrella.h"; sourceTree = ""; }; 2F96DBDA2338122C5D2332063A0DDC4B /* Pods-GradientLoadingBar_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Example.release.xcconfig"; sourceTree = ""; }; 3DF2717E537848B72E4E84211A867E2D /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - 4E083092CBF60F2715011C9F23574CEB /* Observable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Observable.swift; path = Observable/Classes/Observable.swift; sourceTree = ""; }; 4FA583414819F76ADF5F59F2E667585C /* UIColor+CustomColors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UIColor+CustomColors.swift"; sourceTree = ""; }; - 5C876D770BB7FFBD4F9A28FD6ABF273F /* Observable.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Observable.modulemap; sourceTree = ""; }; + 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 6092E73701E3CFB8119BD34B1238E486 /* readme.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = readme.md; sourceTree = ""; }; - 6494464C527430ED4F64A55E9ED0B8A4 /* BottomGradientLoadingBarController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BottomGradientLoadingBarController.swift; path = GradientLoadingBar/Classes/BottomGradientLoadingBarController.swift; sourceTree = ""; }; + 64E0F5A82211B6480066D00D /* GradientLoadingBarViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModel.swift; sourceTree = ""; }; + 64E0F5A92211B6480066D00D /* GradientLoadingBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarController.swift; sourceTree = ""; }; + 64E0F5AA2211B6480066D00D /* BottomGradientLoadingBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomGradientLoadingBarController.swift; sourceTree = ""; }; + 64E0F5AC2211B6480066D00D /* Durations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Durations.swift; sourceTree = ""; }; + 64E0F5AE2211B6480066D00D /* GradientView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; + 64E0F5B02211B6480066D00D /* Disposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Disposable.swift; sourceTree = ""; }; + 64E0F5B12211B6480066D00D /* Observable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = ""; }; + 66A7D431F7F1C404F022C930C937FAF4 /* Pods_GradientLoadingBar_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6B955E6ED6F1FC3FAAD1C08036A4E384 /* Pods-GradientLoadingBar_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-GradientLoadingBar_Example-acknowledgements.markdown"; sourceTree = ""; }; 6BD04847FCD93EA8DB873ED60D7DAFE9 /* Pods-GradientLoadingBar_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-GradientLoadingBar_Tests-dummy.m"; sourceTree = ""; }; - 760501FE4A781A0A4A3BB4EE36D1E128 /* GradientLoadingBarController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GradientLoadingBarController.swift; path = GradientLoadingBar/Classes/GradientLoadingBarController.swift; sourceTree = ""; }; - 7A9DFF1ABED118E9339435332DCDACDB /* Lock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Lock.swift; path = Observable/Classes/Lock.swift; sourceTree = ""; }; + 73CB53E9177A6953693286C0325D1881 /* GradientLoadingBar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GradientLoadingBar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 82F153091821DD341797CA12A8D4CAE1 /* Pods-GradientLoadingBar_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GradientLoadingBar_Tests-umbrella.h"; sourceTree = ""; }; 833F0F13D70DBDC5C2103FB7B32A4551 /* Pods-GradientLoadingBar_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GradientLoadingBar_Tests-resources.sh"; sourceTree = ""; }; - 8DF6AA5B777CE6872A2AC92643E0F757 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 92A830507050E1BD2B0BDFF09D9D3B54 /* Observable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Observable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9396929A9EFCECCA67256186A0F92AB4 /* GradientLoadingBarViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModel.swift; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 94987193A3C956E52823A639B1A63FE9 /* Pods_GradientLoadingBar_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9A04D73ADF1F86BA48555BCA8C37357F /* Pods-GradientLoadingBar_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GradientLoadingBar_Tests-acknowledgements.plist"; sourceTree = ""; }; - 9BE4C26F419339AF6FEB407847B551DC /* Observable-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Observable-dummy.m"; sourceTree = ""; }; A7EE3290A69260383C55CBE340D72011 /* Pods-GradientLoadingBar_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Tests.debug.xcconfig"; sourceTree = ""; }; AA412B257C4E7111197588A95B11802A /* Pods-GradientLoadingBar_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-GradientLoadingBar_Example.modulemap"; sourceTree = ""; }; AB3508D86F5EBCA6A80114494525546D /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - AB823AB93D0C87D58EEC45BFC8B52012 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B09864D350D521BFD6DC7D938FFC10B4 /* GradientLoadingBar-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GradientLoadingBar-prefix.pch"; sourceTree = ""; }; B3929BC42FACCAFF16193DA16F07C92D /* UIColor+DefaultValues.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UIColor+DefaultValues.swift"; sourceTree = ""; }; B611CFC1F8EE4FAEC01581F75425F48F /* Pods-GradientLoadingBar_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GradientLoadingBar_Example-umbrella.h"; sourceTree = ""; }; - C47C72A5BD1CE40555C3CA440845A93E /* Observable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Observable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B9BB15F0F0026C6CDBF8F539B4167BD7 /* Pods_GradientLoadingBar_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C9976B0B1F9BDB6CB4E7204DBD1081B1 /* UIView+AnimateIsHidden.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UIView+AnimateIsHidden.swift"; sourceTree = ""; }; - CD3F66A317040A4DDA2612D78CE827DD /* Durations.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Durations.swift; sourceTree = ""; }; - D0ADA5EF096033B19745A7CAACA917AD /* Observable.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Observable.xcconfig; sourceTree = ""; }; - D12F26C7233A8F032B38D0A935E867C4 /* Disposable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Disposable.swift; path = Observable/Classes/Disposable.swift; sourceTree = ""; }; D1B3EBFC292193F84BD5C4C3A34B09A1 /* Pods-GradientLoadingBar_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GradientLoadingBar_Example-resources.sh"; sourceTree = ""; }; D5977AF0FD89C99333D17D9288C45267 /* Pods-GradientLoadingBar_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GradientLoadingBar_Tests-frameworks.sh"; sourceTree = ""; }; D9DE45D95CCA0E5D76226B173898C17B /* Pods-GradientLoadingBar_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Tests.release.xcconfig"; sourceTree = ""; }; E2E8B226D43266B87011381F86DE1C82 /* Pods-GradientLoadingBar_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GradientLoadingBar_Example-acknowledgements.plist"; sourceTree = ""; }; E38BA62D05FF76C025CDBDB59DF741BB /* Pods-GradientLoadingBar_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GradientLoadingBar_Example-frameworks.sh"; sourceTree = ""; }; - E624F41A654173DCD2381FB6014330B4 /* ImmutableObservable+ObserveDistinct.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "ImmutableObservable+ObserveDistinct.swift"; sourceTree = ""; }; E81C4CEB4E6A0793321B9591E1BD1B69 /* GradientLoadingBar-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GradientLoadingBar-dummy.m"; sourceTree = ""; }; EADFB0EFFF6A08CAA2D4588D6C2F0C44 /* Pods-GradientLoadingBar_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-GradientLoadingBar_Example-dummy.m"; sourceTree = ""; }; - F09C3971033EB7D38DBDAA4976E7E9F4 /* Observable-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Observable-umbrella.h"; sourceTree = ""; }; F0F91F53502405804E4AFA6E2F5FF2A8 /* Pods-GradientLoadingBar_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Example.debug.xcconfig"; sourceTree = ""; }; F12B1D26E2D5D57764C939C2F578BAEB /* GradientLoadingBar.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; path = GradientLoadingBar.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; F82CB34C43ED6C79BDB849534EA2690D /* GradientLoadingBar.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GradientLoadingBar.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 547F46A5998EEECDDEB56536CC6BF2B3 /* Frameworks */ = { + 04B648C597C17615A838E7D583A32623 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 87C19438979525BA0DBAA582FB6A5B12 /* Foundation.framework in Frameworks */, + 69C76C33449FEBFF78BBDC94EE694EC5 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 9F4B955C5BDC3ACF74B9AC184E5AF641 /* Frameworks */ = { + CA93BE6773832F78EAF204758D4DDADB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 06C24252C63A62B4D962275EB05B9EA9 /* Foundation.framework in Frameworks */, - 34278664DAA67E936663F4E01FA8CDFC /* Observable.framework in Frameworks */, + A90FED5348717F4A397D32FEDF1C7EEB /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -148,14 +117,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - F647AA8CBE0A1F1C353CFA2CB5B2AB2E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3D3EFA7D54862F41E53DFB5ACCE9D0D5 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -182,47 +143,9 @@ path = "Example/Pods/Target Support Files/GradientLoadingBar"; sourceTree = ""; }; - 082E6D9C47258D3165EB6CDB3EA77F12 /* ViewModel */ = { - isa = PBXGroup; - children = ( - 9396929A9EFCECCA67256186A0F92AB4 /* GradientLoadingBarViewModel.swift */, - ); - name = ViewModel; - path = GradientLoadingBar/Classes/ViewModel; - sourceTree = ""; - }; - 096789584DD71B47C937802191E13B7F /* ImmutableObservable */ = { - isa = PBXGroup; - children = ( - E624F41A654173DCD2381FB6014330B4 /* ImmutableObservable+ObserveDistinct.swift */, - ); - path = ImmutableObservable; - sourceTree = ""; - }; - 1513AE4EB0D83B9C337A659FFBF69379 /* Views */ = { - isa = PBXGroup; - children = ( - 2E9A49BCAE8F8EB569BE0321D71C6CF3 /* GradientView.swift */, - ); - name = Views; - path = GradientLoadingBar/Classes/Views; - sourceTree = ""; - }; - 20E70D97A2915DA6914F9C107FDBBE1E /* Products */ = { - isa = PBXGroup; - children = ( - 29F34B3709A0B91080A953ED30B6C8F6 /* GradientLoadingBar.framework */, - 92A830507050E1BD2B0BDFF09D9D3B54 /* Observable.framework */, - 284E5B1E5B78675A430CFB3C83D79E8F /* Pods_GradientLoadingBar_Example.framework */, - 94987193A3C956E52823A639B1A63FE9 /* Pods_GradientLoadingBar_Tests.framework */, - ); - name = Products; - sourceTree = ""; - }; 27810AFA66EEB9E1D13EDAD15AD52FE2 /* Extensions */ = { isa = PBXGroup; children = ( - 096789584DD71B47C937802191E13B7F /* ImmutableObservable */, 0070ECA695D45AEAF421D7603C125175 /* UIColor */, 570474625B940C88744C1F657E4EDF5C /* UIView */, ); @@ -230,13 +153,6 @@ path = GradientLoadingBar/Classes/Extensions; sourceTree = ""; }; - 2F4DE0864561DF33CF245E0598CD3A4A /* SwiftLint */ = { - isa = PBXGroup; - children = ( - ); - path = SwiftLint; - sourceTree = ""; - }; 2F5986BA41C59FC4798632C728EEE280 /* Pods-GradientLoadingBar_Tests */ = { isa = PBXGroup; children = ( @@ -263,6 +179,13 @@ name = "Development Pods"; sourceTree = ""; }; + 37843AFB400D5948266EFF83D844D298 /* SwiftLint */ = { + isa = PBXGroup; + children = ( + ); + path = SwiftLint; + sourceTree = ""; + }; 4660D1E702B3D84E997AF8A7102A8A7A /* Pod */ = { isa = PBXGroup; children = ( @@ -273,6 +196,15 @@ name = Pod; sourceTree = ""; }; + 4FAF764B0968FA76D985E563B50F54AF /* Pods */ = { + isa = PBXGroup; + children = ( + C5603D18FA3FACCD8B1248AA66F68D0F /* SwiftFormat */, + 37843AFB400D5948266EFF83D844D298 /* SwiftLint */, + ); + name = Pods; + sourceTree = ""; + }; 570474625B940C88744C1F657E4EDF5C /* UIView */ = { isa = PBXGroup; children = ( @@ -284,27 +216,76 @@ 5796E49B32456FEE45DB346F8574F3E4 /* GradientLoadingBar */ = { isa = PBXGroup; children = ( - 6494464C527430ED4F64A55E9ED0B8A4 /* BottomGradientLoadingBarController.swift */, - 760501FE4A781A0A4A3BB4EE36D1E128 /* GradientLoadingBarController.swift */, 27810AFA66EEB9E1D13EDAD15AD52FE2 /* Extensions */, + 64E0F5A52211B6480066D00D /* Feature */, 4660D1E702B3D84E997AF8A7102A8A7A /* Pod */, - A71FEFA95E570C875EF43DDB68789C11 /* Structs */, 04419D4B33396FCF086D7C4BCEC7303A /* Support Files */, - 082E6D9C47258D3165EB6CDB3EA77F12 /* ViewModel */, - 1513AE4EB0D83B9C337A659FFBF69379 /* Views */, ); name = GradientLoadingBar; path = ../..; sourceTree = ""; }; - 774E2C2EDBBCC7DB1A7BB79B0E2215B6 /* Pods */ = { + 5E0D919E635D23B70123790B8308F8EF /* iOS */ = { isa = PBXGroup; children = ( - EB6BDD487872A7AE4335EF4AF9DBE8F7 /* Observable */, - AB936E3A191BACCB449B70EEC4F262F3 /* SwiftFormat */, - 2F4DE0864561DF33CF245E0598CD3A4A /* SwiftLint */, + 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */, ); - name = Pods; + name = iOS; + sourceTree = ""; + }; + 64E0F5A52211B6480066D00D /* Feature */ = { + isa = PBXGroup; + children = ( + 64E0F5A62211B6480066D00D /* GradientLoadingBar */, + 64E0F5AF2211B6480066D00D /* Observable */, + ); + name = Feature; + path = GradientLoadingBar/Classes/Feature; + sourceTree = ""; + }; + 64E0F5A62211B6480066D00D /* GradientLoadingBar */ = { + isa = PBXGroup; + children = ( + 64E0F5A92211B6480066D00D /* GradientLoadingBarController.swift */, + 64E0F5AA2211B6480066D00D /* BottomGradientLoadingBarController.swift */, + 64E0F5AB2211B6480066D00D /* Structs */, + 64E0F5A72211B6480066D00D /* ViewModel */, + 64E0F5AD2211B6480066D00D /* Views */, + ); + path = GradientLoadingBar; + sourceTree = ""; + }; + 64E0F5A72211B6480066D00D /* ViewModel */ = { + isa = PBXGroup; + children = ( + 64E0F5A82211B6480066D00D /* GradientLoadingBarViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + 64E0F5AB2211B6480066D00D /* Structs */ = { + isa = PBXGroup; + children = ( + 64E0F5AC2211B6480066D00D /* Durations.swift */, + ); + path = Structs; + sourceTree = ""; + }; + 64E0F5AD2211B6480066D00D /* Views */ = { + isa = PBXGroup; + children = ( + 64E0F5AE2211B6480066D00D /* GradientView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 64E0F5AF2211B6480066D00D /* Observable */ = { + isa = PBXGroup; + children = ( + 64E0F5B02211B6480066D00D /* Disposable.swift */, + 64E0F5B12211B6480066D00D /* Observable.swift */, + ); + path = Observable; sourceTree = ""; }; 7DB346D0F39D3F0E887471402A8071AB = { @@ -312,9 +293,9 @@ children = ( 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 35F815A779EA5FFFC0841A34A6CB53B4 /* Development Pods */, - D57806A1B7868A30C55CD96489B178E5 /* Frameworks */, - 774E2C2EDBBCC7DB1A7BB79B0E2215B6 /* Pods */, - 20E70D97A2915DA6914F9C107FDBBE1E /* Products */, + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, + 4FAF764B0968FA76D985E563B50F54AF /* Pods */, + A75F0CAF38E4AF1AFB98941ED812A427 /* Products */, 89EC43461F8350C8C85CBAA922CE7FC3 /* Targets Support Files */, ); sourceTree = ""; @@ -328,53 +309,31 @@ name = "Targets Support Files"; sourceTree = ""; }; - 91E52B6A4D0399DEC177B4245278E3EB /* iOS */ = { + A75F0CAF38E4AF1AFB98941ED812A427 /* Products */ = { isa = PBXGroup; children = ( - 8DF6AA5B777CE6872A2AC92643E0F757 /* Foundation.framework */, + 73CB53E9177A6953693286C0325D1881 /* GradientLoadingBar.framework */, + 66A7D431F7F1C404F022C930C937FAF4 /* Pods_GradientLoadingBar_Example.framework */, + B9BB15F0F0026C6CDBF8F539B4167BD7 /* Pods_GradientLoadingBar_Tests.framework */, ); - name = iOS; + name = Products; sourceTree = ""; }; - A71FEFA95E570C875EF43DDB68789C11 /* Structs */ = { + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { isa = PBXGroup; children = ( - CD3F66A317040A4DDA2612D78CE827DD /* Durations.swift */, + 5E0D919E635D23B70123790B8308F8EF /* iOS */, ); - name = Structs; - path = GradientLoadingBar/Classes/Structs; + name = Frameworks; sourceTree = ""; }; - AB936E3A191BACCB449B70EEC4F262F3 /* SwiftFormat */ = { + C5603D18FA3FACCD8B1248AA66F68D0F /* SwiftFormat */ = { isa = PBXGroup; children = ( ); path = SwiftFormat; sourceTree = ""; }; - BC183C1A51D4C9A64C5C628CDD8081A0 /* Support Files */ = { - isa = PBXGroup; - children = ( - AB823AB93D0C87D58EEC45BFC8B52012 /* Info.plist */, - 5C876D770BB7FFBD4F9A28FD6ABF273F /* Observable.modulemap */, - D0ADA5EF096033B19745A7CAACA917AD /* Observable.xcconfig */, - 9BE4C26F419339AF6FEB407847B551DC /* Observable-dummy.m */, - 2F1BDD41157523D250EC77DD1B9034EE /* Observable-prefix.pch */, - F09C3971033EB7D38DBDAA4976E7E9F4 /* Observable-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/Observable"; - sourceTree = ""; - }; - D57806A1B7868A30C55CD96489B178E5 /* Frameworks */ = { - isa = PBXGroup; - children = ( - C47C72A5BD1CE40555C3CA440845A93E /* Observable.framework */, - 91E52B6A4D0399DEC177B4245278E3EB /* iOS */, - ); - name = Frameworks; - sourceTree = ""; - }; D78297D5D15B07F65F5BE3EFB324B611 /* Pods-GradientLoadingBar_Example */ = { isa = PBXGroup; children = ( @@ -393,33 +352,14 @@ path = "Target Support Files/Pods-GradientLoadingBar_Example"; sourceTree = ""; }; - EB6BDD487872A7AE4335EF4AF9DBE8F7 /* Observable */ = { - isa = PBXGroup; - children = ( - D12F26C7233A8F032B38D0A935E867C4 /* Disposable.swift */, - 7A9DFF1ABED118E9339435332DCDACDB /* Lock.swift */, - 4E083092CBF60F2715011C9F23574CEB /* Observable.swift */, - BC183C1A51D4C9A64C5C628CDD8081A0 /* Support Files */, - ); - path = Observable; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 36CFA0E317445AA3F426C5E6359C390B /* Headers */ = { + 1F791A809647DFE0FCC3CB2168083021 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 49D1C6D426F426DAADCA0326273AAC42 /* GradientLoadingBar-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - BC9F5E2153F74FA1A3F5DD3045CFB84B /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 166F1654BD9D0C8E3FD189C976E4DD8A /* Observable-umbrella.h in Headers */, + 9AAC7020094626B3D3716199EF579DB3 /* Pods-GradientLoadingBar_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -431,52 +371,32 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - E45FB182CB503AA3F930BC401966B247 /* Headers */ = { + E59C7723E248CDEEF420D56FA140BF2C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 1B508C3732F51FCEB0F4635A802DADCA /* Pods-GradientLoadingBar_Example-umbrella.h in Headers */, + 17B6325C9E108764B460015F7191B83A /* GradientLoadingBar-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 8021F4FFF4A5140BF1448C374162E69D /* GradientLoadingBar */ = { + B9D0FA9CCBF200478C7FA87EEDD00505 /* GradientLoadingBar */ = { isa = PBXNativeTarget; - buildConfigurationList = CD5D02C23EF87F57EED28E51B9B36921 /* Build configuration list for PBXNativeTarget "GradientLoadingBar" */; + buildConfigurationList = 193632B0CD1946086175FEBB0B45EE24 /* Build configuration list for PBXNativeTarget "GradientLoadingBar" */; buildPhases = ( - 83906F4AAE15A6978B6A377F9B2DF31C /* Sources */, - 9F4B955C5BDC3ACF74B9AC184E5AF641 /* Frameworks */, - 36CFA0E317445AA3F426C5E6359C390B /* Headers */, + 127050EB10E7C3EFFFA18E452B72A29D /* Sources */, + 04B648C597C17615A838E7D583A32623 /* Frameworks */, + E59C7723E248CDEEF420D56FA140BF2C /* Headers */, ); buildRules = ( ); dependencies = ( - 07DFF0AE96562F181653A85CB7506889 /* PBXTargetDependency */, ); name = GradientLoadingBar; productName = GradientLoadingBar; - productReference = 29F34B3709A0B91080A953ED30B6C8F6 /* GradientLoadingBar.framework */; - productType = "com.apple.product-type.framework"; - }; - C9E360AE7E621FF686F7C060178481D1 /* Pods-GradientLoadingBar_Example */ = { - isa = PBXNativeTarget; - buildConfigurationList = CE51B32DA3B3093FF3BA59642B6C54A8 /* Build configuration list for PBXNativeTarget "Pods-GradientLoadingBar_Example" */; - buildPhases = ( - 652F4121229E4DEADA081DDBD3ED8583 /* Sources */, - F647AA8CBE0A1F1C353CFA2CB5B2AB2E /* Frameworks */, - E45FB182CB503AA3F930BC401966B247 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - F0D652528A64CFF6B7D836DAAA8C7AEE /* PBXTargetDependency */, - 8F53C1FF4329F6085BB69BF395E65785 /* PBXTargetDependency */, - ); - name = "Pods-GradientLoadingBar_Example"; - productName = "Pods-GradientLoadingBar_Example"; - productReference = 284E5B1E5B78675A430CFB3C83D79E8F /* Pods_GradientLoadingBar_Example.framework */; + productReference = 73CB53E9177A6953693286C0325D1881 /* GradientLoadingBar.framework */; productType = "com.apple.product-type.framework"; }; D164F5795779D3319394A96B11FB0202 /* Pods-GradientLoadingBar_Tests */ = { @@ -494,24 +414,25 @@ ); name = "Pods-GradientLoadingBar_Tests"; productName = "Pods-GradientLoadingBar_Tests"; - productReference = 94987193A3C956E52823A639B1A63FE9 /* Pods_GradientLoadingBar_Tests.framework */; + productReference = B9BB15F0F0026C6CDBF8F539B4167BD7 /* Pods_GradientLoadingBar_Tests.framework */; productType = "com.apple.product-type.framework"; }; - E6CCE0B41A1F307B9A6DBB1AB60162D3 /* Observable */ = { + F66315F62F3F426F979FBA688C95BB49 /* Pods-GradientLoadingBar_Example */ = { isa = PBXNativeTarget; - buildConfigurationList = C93431B6223623F7EB33122207BA24F4 /* Build configuration list for PBXNativeTarget "Observable" */; + buildConfigurationList = E601522F10F0A9815FBCF79471D8A16C /* Build configuration list for PBXNativeTarget "Pods-GradientLoadingBar_Example" */; buildPhases = ( - 92162E574DC3296EC971DA88A017065C /* Sources */, - 547F46A5998EEECDDEB56536CC6BF2B3 /* Frameworks */, - BC9F5E2153F74FA1A3F5DD3045CFB84B /* Headers */, + A36F03C1DF22C7A165896095D57BB569 /* Sources */, + CA93BE6773832F78EAF204758D4DDADB /* Frameworks */, + 1F791A809647DFE0FCC3CB2168083021 /* Headers */, ); buildRules = ( ); dependencies = ( + 69A90CA62BF02B2DE72D25590B362722 /* PBXTargetDependency */, ); - name = Observable; - productName = Observable; - productReference = 92A830507050E1BD2B0BDFF09D9D3B54 /* Observable.framework */; + name = "Pods-GradientLoadingBar_Example"; + productName = "Pods-GradientLoadingBar_Example"; + productReference = 66A7D431F7F1C404F022C930C937FAF4 /* Pods_GradientLoadingBar_Example.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -521,7 +442,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0930; - LastUpgradeCheck = 1010; + LastUpgradeCheck = 0930; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; @@ -531,19 +452,36 @@ en, ); mainGroup = 7DB346D0F39D3F0E887471402A8071AB; - productRefGroup = 20E70D97A2915DA6914F9C107FDBBE1E /* Products */; + productRefGroup = A75F0CAF38E4AF1AFB98941ED812A427 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 8021F4FFF4A5140BF1448C374162E69D /* GradientLoadingBar */, - E6CCE0B41A1F307B9A6DBB1AB60162D3 /* Observable */, - C9E360AE7E621FF686F7C060178481D1 /* Pods-GradientLoadingBar_Example */, + B9D0FA9CCBF200478C7FA87EEDD00505 /* GradientLoadingBar */, + F66315F62F3F426F979FBA688C95BB49 /* Pods-GradientLoadingBar_Example */, D164F5795779D3319394A96B11FB0202 /* Pods-GradientLoadingBar_Tests */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ + 127050EB10E7C3EFFFA18E452B72A29D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 64E0F5B82211B6480066D00D /* Observable.swift in Sources */, + 55AF16C7929CCE114DEBD48918B190AF /* GradientLoadingBar-dummy.m in Sources */, + 7D1E168D6E79E03F2960CE51E513D634 /* UIColor+CustomColors.swift in Sources */, + 64E0F5B32211B6480066D00D /* GradientLoadingBarController.swift in Sources */, + 64E0F5B52211B6480066D00D /* Durations.swift in Sources */, + 6546432CC49E569B81E2DC4BC3C9A2CB /* UIColor+DefaultValues.swift in Sources */, + 64E0F5B42211B6480066D00D /* BottomGradientLoadingBarController.swift in Sources */, + AA3F823EE392DA32CB961B91615BC96E /* UIView+AnimateIsHidden.swift in Sources */, + 64E0F5B72211B6480066D00D /* Disposable.swift in Sources */, + 64E0F5B22211B6480066D00D /* GradientLoadingBarViewModel.swift in Sources */, + 64E0F5B62211B6480066D00D /* GradientView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 444AFD9DC935A469A9B149EFCACF8E36 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -552,69 +490,29 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 652F4121229E4DEADA081DDBD3ED8583 /* Sources */ = { + A36F03C1DF22C7A165896095D57BB569 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 42C9B868EFF007C954640D7937E4D31F /* Pods-GradientLoadingBar_Example-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 83906F4AAE15A6978B6A377F9B2DF31C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 27B4FA1102726CB66B225E9DE43EC19C /* BottomGradientLoadingBarController.swift in Sources */, - 13E8860F705BD1002D6164AD341B92FE /* Durations.swift in Sources */, - 132267F3B4E9CA753A6BF27134FC5465 /* GradientLoadingBar-dummy.m in Sources */, - 52162FA2A406B07682707EC00E7960DF /* GradientLoadingBarController.swift in Sources */, - F182892639AF608EAABE0D4A0E6EBCE5 /* GradientLoadingBarViewModel.swift in Sources */, - 9F6FF95266983E325B01A3F72BECF50A /* GradientView.swift in Sources */, - A5C8E5782BE408C3EEFF5037E768B616 /* ImmutableObservable+ObserveDistinct.swift in Sources */, - 73B71B1D4D56F9B366CB5ACF26F15B88 /* UIColor+CustomColors.swift in Sources */, - FAFE554D7816324CC184B0DF6CC8BDD8 /* UIColor+DefaultValues.swift in Sources */, - 03F61FA0724C4C3A8DFE7939D7D0F1C5 /* UIView+AnimateIsHidden.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 92162E574DC3296EC971DA88A017065C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - AC929579BF66F38833EF4B5876165250 /* Disposable.swift in Sources */, - E2BF83D2ECC7B2674EF43F97BA433431 /* Lock.swift in Sources */, - 7307623495DBF963E150BA3B5EEEC109 /* Observable-dummy.m in Sources */, - 59811596DEE4F2CF46FED33B8125FB07 /* Observable.swift in Sources */, + 3CAA7A728F43E1EB82993F0868BBC0AF /* Pods-GradientLoadingBar_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 07DFF0AE96562F181653A85CB7506889 /* PBXTargetDependency */ = { + 69A90CA62BF02B2DE72D25590B362722 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Observable; - target = E6CCE0B41A1F307B9A6DBB1AB60162D3 /* Observable */; - targetProxy = 14097629F04F80655A04663B59127D8D /* PBXContainerItemProxy */; - }; - 8F53C1FF4329F6085BB69BF395E65785 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Observable; - target = E6CCE0B41A1F307B9A6DBB1AB60162D3 /* Observable */; - targetProxy = 11F0ABF401134D6A07D63CBB85302D0B /* PBXContainerItemProxy */; + name = GradientLoadingBar; + target = B9D0FA9CCBF200478C7FA87EEDD00505 /* GradientLoadingBar */; + targetProxy = 0A4C5EB7B411D126BCF5E8AEED59062F /* PBXContainerItemProxy */; }; EBBB4A15C4052D49212F0305047096A5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Pods-GradientLoadingBar_Example"; - target = C9E360AE7E621FF686F7C060178481D1 /* Pods-GradientLoadingBar_Example */; + target = F66315F62F3F426F979FBA688C95BB49 /* Pods-GradientLoadingBar_Example */; targetProxy = 055D89AD234219F98CADD8FE2D43783D /* PBXContainerItemProxy */; }; - F0D652528A64CFF6B7D836DAAA8C7AEE /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = GradientLoadingBar; - target = 8021F4FFF4A5140BF1448C374162E69D /* GradientLoadingBar */; - targetProxy = 9BBDC016F505E44F0E066512798A7A25 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -714,40 +612,7 @@ }; name = Debug; }; - 501CFA2A56280DF630588BC27442110B /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D0ADA5EF096033B19745A7CAACA917AD /* Observable.xcconfig */; - buildSettings = { - 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/Observable/Observable-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Observable/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Observable/Observable.modulemap"; - PRODUCT_MODULE_NAME = Observable; - PRODUCT_NAME = Observable; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 53F80379749E33DC79139A7590D1D755 /* Debug */ = { + 58FB25CCBECC869CEE6866634F76F03C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F82CB34C43ED6C79BDB849534EA2690D /* GradientLoadingBar.xcconfig */; buildSettings = { @@ -779,41 +644,9 @@ }; name = Debug; }; - 65B06DC32E3E86709DB683164DC92DB8 /* Debug */ = { + 66846996BE21F5BE7BF6038586FBDCBE /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D0ADA5EF096033B19745A7CAACA917AD /* Observable.xcconfig */; - buildSettings = { - 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/Observable/Observable-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Observable/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Observable/Observable.modulemap"; - PRODUCT_MODULE_NAME = Observable; - PRODUCT_NAME = Observable; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 91006A8C9F195DD1CAB09474462C7E35 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F0F91F53502405804E4AFA6E2F5FF2A8 /* Pods-GradientLoadingBar_Example.debug.xcconfig */; + baseConfigurationReference = 2F96DBDA2338122C5D2332063A0DDC4B /* Pods-GradientLoadingBar_Example.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; @@ -838,13 +671,13 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; A0B69D80C4C14FBCA8817D066A4BAB2F /* Release */ = { isa = XCBuildConfiguration; @@ -880,7 +713,7 @@ }; name = Release; }; - C2C308C0ADA0EC24763DCF184D322D3C /* Release */ = { + A5D2B3EFB5F0DC9832ADDE778E3E58D5 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = F82CB34C43ED6C79BDB849534EA2690D /* GradientLoadingBar.xcconfig */; buildSettings = { @@ -913,6 +746,41 @@ }; name = Release; }; + F62DAF1A51EBAD389868DE5F387D7C1B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F0F91F53502405804E4AFA6E2F5FF2A8 /* Pods-GradientLoadingBar_Example.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + 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"; + INFOPLIST_FILE = "Target Support Files/Pods-GradientLoadingBar_Example/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; FDB2FC4A1E5891381CD9D922145497F1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -967,49 +835,22 @@ MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; SYMROOT = "${SRCROOT}/../build"; }; name = Release; }; - FF3EC82D752FB62021AA7B2D872DE631 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2F96DBDA2338122C5D2332063A0DDC4B /* Pods-GradientLoadingBar_Example.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - 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"; - INFOPLIST_FILE = "Target Support Files/Pods-GradientLoadingBar_Example/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 193632B0CD1946086175FEBB0B45EE24 /* Build configuration list for PBXNativeTarget "GradientLoadingBar" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58FB25CCBECC869CEE6866634F76F03C /* Debug */, + A5D2B3EFB5F0DC9832ADDE778E3E58D5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1028,29 +869,11 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C93431B6223623F7EB33122207BA24F4 /* Build configuration list for PBXNativeTarget "Observable" */ = { + E601522F10F0A9815FBCF79471D8A16C /* Build configuration list for PBXNativeTarget "Pods-GradientLoadingBar_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( - 65B06DC32E3E86709DB683164DC92DB8 /* Debug */, - 501CFA2A56280DF630588BC27442110B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CD5D02C23EF87F57EED28E51B9B36921 /* Build configuration list for PBXNativeTarget "GradientLoadingBar" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 53F80379749E33DC79139A7590D1D755 /* Debug */, - C2C308C0ADA0EC24763DCF184D322D3C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CE51B32DA3B3093FF3BA59642B6C54A8 /* Build configuration list for PBXNativeTarget "Pods-GradientLoadingBar_Example" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 91006A8C9F195DD1CAB09474462C7E35 /* Debug */, - FF3EC82D752FB62021AA7B2D872DE631 /* Release */, + F62DAF1A51EBAD389868DE5F387D7C1B /* Debug */, + 66846996BE21F5BE7BF6038586FBDCBE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/Pods/SwiftFormat/CommandLineTool/swiftformat b/Example/Pods/SwiftFormat/CommandLineTool/swiftformat index a8a9ad5..310591d 100755 Binary files a/Example/Pods/SwiftFormat/CommandLineTool/swiftformat and b/Example/Pods/SwiftFormat/CommandLineTool/swiftformat differ diff --git a/Example/Pods/SwiftFormat/README.md b/Example/Pods/SwiftFormat/README.md index b2b1087..2b2615d 100644 --- a/Example/Pods/SwiftFormat/README.md +++ b/Example/Pods/SwiftFormat/README.md @@ -1,6 +1,5 @@ [![Travis](https://img.shields.io/travis/nicklockwood/SwiftFormat.svg)](https://travis-ci.org/nicklockwood/SwiftFormat) [![Coveralls](https://coveralls.io/repos/github/nicklockwood/SwiftFormat/badge.svg)](https://coveralls.io/github/nicklockwood/SwiftFormat) -[![Swift 3.4](https://img.shields.io/badge/swift-3.4-orange.svg?style=flat)](https://developer.apple.com/swift) [![Swift 4.2](https://img.shields.io/badge/swift-4.2-red.svg?style=flat)](https://developer.apple.com/swift) [![License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://opensource.org/licenses/MIT) [![Twitter](https://img.shields.io/badge/twitter-@nicklockwood-blue.svg)](http://twitter.com/nicklockwood) @@ -14,17 +13,20 @@ Table of Contents - [Command-line tool](#command-line-tool) - [Xcode source editor extension](#xcode-source-editor-extension) - [Xcode build phase](#xcode-build-phase) + - [Via Applescript](#via-applescript) - [VSCode plugin](#vscode-plugin) - [Git pre-commit hook](#git-pre-commit-hook) - [On CI using Danger](#on-ci-using-danger) -- [Usage](#so-what-does-swiftformat-actually-do) +- [Configuration](#configuration) - [Options](#options) - [Rules](#rules) - - [Config](#config) + - [Swift version](#swift-version) + - [Config file](#config-file) + - [Globs](#globs) - [Linting](#linting) + - [Cache](#cache) + - [File headers](#file-headers) - [FAQ](#faq) -- [Cache](#cache) -- [File headers](#file-headers) - [Known issues](#known-issues) - [Credits](#credits) @@ -32,19 +34,18 @@ Table of Contents What is this? ---------------- -SwiftFormat is a code library and command-line tool for reformatting swift code. - -It applies a set of rules to the formatting and space around the code, leaving the behavior intact. +SwiftFormat is a code library and command-line tool for reformatting swift code on macOS or Linux. +SwiftFormat goes above and beyond what you might expect from a code formatter. In addition to adjusting white space it can insert or remove implicit `self`, remove redundant parentheses, and correct many other deviations from the standard Swift idioms. Why would I want to do that? ----------------------------- Many programmers have a preferred style for formatting their code, and others seem entirely blind to the existing formatting conventions of a project (to the enragement of their colleagues). -When collaborating on a project, it can be helpful to agree on a common coding style, but enforcing that manually is tedious and error-prone, and can lead to bad feeling if some participants take it more seriously than others. +When collaborating on a project, it can be helpful to agree on a common coding style, but enforcing that manually is tedious and error-prone, and can lead to arguments if some participants take it more seriously than others. -Having a tool to automatically enforce a common style eliminates those issues, and lets you focus on the *operation* of the code, not its presentation. +Having a tool to automatically enforce a common style eliminates those issues, and lets you focus on the behavior of the code, not its presentation. How do I install it? @@ -63,26 +64,34 @@ Command-line tool **Installation:** -You can install the `swiftformat` command-line tool using [Homebrew](http://brew.sh/). Assuming you already have Homebrew installed, just type: +You can install the `swiftformat` command-line tool on macOS using [Homebrew](http://brew.sh/). Assuming you already have Homebrew installed, just type: ```bash -> brew update -> brew install swiftformat +$ brew update +$ brew install swiftformat ``` -Alternatively, you can install the tool using [Mint](https://github.com/yonaskolb/Mint) as follows: +Alternatively, you can install the tool on macOS or Linux by using [Mint](https://github.com/yonaskolb/Mint) as follows: ```bash -> mint install nicklockwood/SwiftFormat +$ mint install nicklockwood/SwiftFormat ``` And then run it using: ```bash -> mint run swiftformat +$ mint run swiftformat ``` -If you are installing SwiftFormat into your project directory, you can use [CocoaPods](https://cocoapods.org/) to automatically install the swiftformat binary along with your other pods - see the Xcode build phase instructions below for details. +Or if you prefer, you can check out and build SwiftFormat manually on macOS or Linux as follows: + +```bash +$ git clone https://github.com/nicklockwood/SwiftFormat +$ cd SwiftFormat +$ swift build -c release +``` + +If you are installing SwiftFormat into your project directory, you can use [CocoaPods](https://cocoapods.org/) on macOS to automatically install the swiftformat binary along with your other pods - see the Xcode build phase instructions below for details. If you would prefer not to use a package manager, you can build the command-line app manually: @@ -101,7 +110,7 @@ If you would prefer not to use a package manager, you can build the command-line If you followed the installation instructions above, you can now just type ```bash -> swiftformat . +$ swiftformat . ``` (that's a space and then a period after the command) in the terminal to format any Swift files in the current directory. @@ -122,7 +131,7 @@ To use it safely, do the following: If you used `--inferoptions` to generate a suggested set of options in step 3, you should copy and paste them into the command, either before or after the path(s) to your source files. - If you have created a [configuration file](#config), you can specify its path using `--config "/path/to/your/config-file/". + If you have created a [config file](#config-file), you can specify its path using `--config "/path/to/your/config-file/". 5. Press enter to begin formatting. Once the formatting is complete, use your source control system to check the changes, and verify that no undesirable changes have been introduced. If they have, revert the changes, tweak the options and try again. @@ -133,7 +142,7 @@ Following these instructions *should* ensure that you avoid catastrophic data lo If you prefer, you can also use unix pipes to include swiftformat as part of a command chain. For example, this is an alternative way to format a file: ```bash -> cat /path/to/file.swift | swiftformat --output /path/to/file.swift +$ cat /path/to/file.swift | swiftformat --output /path/to/file.swift ``` Omitting the `--output /path/to/file.swift` will print the formatted file to `stdout`. @@ -154,7 +163,7 @@ In Xcode, you'll find a SwiftFormat option under the Editor menu. You can use th You can configure the formatting [rules](#rules) and [options](#options) used by the Xcode source editor extension using the host application. There is currently no way to override these per-project, however you can import and export different configurations using the File menu. You will need to do this again each time you switch project. -The format of the configuration file is described in the [Config section](#config) below. +The format of the configuration file is described in the [Config section](#config-file) below. **Note:** SwiftFormat for Xcode cannot automatically detect changes to an imported configuration file. If you update the `.swiftformat` file for your project, you will need to manually re-import that file into SwiftFormat for Xcode in order for the Xcode source editor extension to use the new configuration. @@ -178,7 +187,7 @@ To set up SwiftFormat as an Xcode build phase, do the following: "${SRCROOT}/path/to/swiftformat" "${SRCROOT}/path/to/your/swift/code/" ``` - Both paths should be relative to the directory containing your Xcode project. If you are installing SwiftFormat as a Cocoapod, the swiftformat path will be + Both paths should be relative to the directory containing your Xcode project. If you are installing SwiftFormat using Cocoapods, the path will be ```bash "${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat" @@ -198,6 +207,20 @@ fi This is not recommended for shared projects however, as different team members using different versions of SwiftFormat may result in noise in the commits as code gets reformatted inconsistently. +Via AppleScript +---------------- + +To run swiftformat on the frontmost Xcode document (project or workspace) you can use the following AppleScript: + +```applescript +tell application "Xcode" + set frontWindow to the first window + set myPath to path of document of frontWindow + do shell script "cd " & myPath & ";cd ..; /usr/local/bin/swiftformat ." +end tell +``` + +Some Apps you can trigger this from are [BetterTouchTool](https://folivora.ai), [Alfred](https://www.alfredapp.com) or [Keyboard Maestro](https://www.keyboardmaestro.com/main/). Another option is to define a QuickAction for Xcode via Automator and then assign a keyboard shortcut for it in the System Preferences. VSCode plugin -------------- @@ -247,10 +270,8 @@ To setup SwiftFormat to be used by your continuous integration system using [Dan **NOTE:** It is recommended to add the `swiftformat` binary to your project directory to ensure the same version is used each time (see the [Xcode build phase](#xcode-build-phase) instructions above). -So what does SwiftFormat actually do? --------------------------------------- - -SwiftFormat first converts the source file into tokens, then iteratively applies a set of rules to the tokens to adjust the formatting. The tokens are then converted back into text. +Configuration +------------- SwiftFormat's configuration is split between **rules** and **options**. Rules are functions in the SwiftFormat library that apply changes to the code. Options are settings that control the behavior of the rules. @@ -260,7 +281,7 @@ Options The options available in SwiftFormat can be displayed using the `--help` command-line argument. The default value for each option is indicated in the help text. -Rules are configured by adding `--[rulename] [value]` to your command-line arguments, or by creating a [config file](#config) as explained below. +Rules are configured by adding `--[rulename] [value]` to your command-line arguments, or by creating a [config file](#config-file) as explained below. A given option may affect multiple rules. See the [Rules](#rules) section below for details about which options affect which rule. @@ -308,10 +329,41 @@ let bar = baz // rule(s) will be re-enabled for this line There is no need to manually re-enable a rule after using the `next` directive. -**Note:** The `swiftformat:enable` directives only serves to counter a previous `swiftformat:disable` directive in the same file. It is not possible to use `swiftformat:enable` to enable a rule that was not already enabled when formatting started. +**NOTE:** The `swiftformat:enable` directives only serves to counter a previous `swiftformat:disable` directive in the same file. It is not possible to use `swiftformat:enable` to enable a rule that was not already enabled when formatting started. Here are all the rules that SwiftFormat currently applies, and the effects that they have: +***andOperator*** - replaces the `&&` operator with `,` inside `if`, `guard` and `while` conditions: + +```diff +- if true && true { ++ if true, true { +``` + +```diff +- guard true && true else { ++ guard true, true else { +``` + +```diff +- if functionReturnsBool() && true { ++ if functionReturnsBool(), true { +``` + +```diff +- if functionReturnsBool() && variable { ++ if functionReturnsBool(), variable { +``` + +***anyObjectProtocol*** - replaces `class` with `AnyObject` in protocol definitions, as recommended in modern Swift guidelines: + +```diff +- protocol Foo: class {} ++ protocol Foo: AnyObject {} +``` + +**NOTE:** The guideline to use `AnyObject` instead of `class` was only introduced in Swift 4.1, so the `anyObjectProtocol` rule is disabled unless the [swift version](#swift-version) is set to 4.1 or above. + ***blankLinesAtEndOfScope*** - removes trailing blank lines from inside braces, brackets, parens or chevrons: ```diff @@ -598,7 +650,7 @@ Here are all the rules that SwiftFormat currently applies, and the effects that } ``` -***isEmpty*** - replaces `count == 0` checks with `isEmpty`, which is preferred for performance reasons (disabled by default because SwiftFormat is not able to check that the isEmpty property is actually available in all cases): +***isEmpty*** - replaces `count == 0` checks with `isEmpty`, which is preferred for performance reasons (especially for Strings where count has O(n) complexity): ```diff - if foo.count == 0 { @@ -631,7 +683,17 @@ Here are all the rules that SwiftFormat currently applies, and the effects that + let big = 123_456.123 ``` -***ranges*** - controls the spacing around range operators. By default, a space is added, but this can be configured using the `--ranges` option (`spaced` (default) or `nospace`). +***ranges*** - controls the spacing around range operators. By default, a space is added, but this can be configured using the `--ranges` option (`spaced` (default) or `nospace`): + +```diff +- for i in 0..<5 {} ++ for i in 0 ..< 5 {} +``` + +```diff +- if (0...5).contains(i) {} ++ if (0 ... 5).contains(i) {} +``` ***redundantBackticks*** - removes unnecessary escaping of identifiers using backticks, e.g. in cases where the escaped word is not a keyword, or is not ambiguous in that context: @@ -645,6 +707,19 @@ Here are all the rules that SwiftFormat currently applies, and the effects that + func foo(with default: Int) {} ``` +***redundantBreak*** - removes redundant `break` statements from inside switch cases: + +```diff + switch foo { + case bar: + print("bar") +- break + default: + print("default") +- break + } +``` + ***redundantGet*** - removes unnecessary `get { }` clauses from inside read-only computed properties: ```diff @@ -659,21 +734,52 @@ Here are all the rules that SwiftFormat currently applies, and the effects that } ``` +***redundantExtensionACL*** - removes access control level keywords from extension members when the access level matches the extension itself: + +```diff + var foo: Int { +- get { +- return 5 +- } + } + + var foo: Int { ++ return 5 + } +``` + +***redundantFileprivate*** - replaces `fileprivate` access control keyword with `private` when they are equivalent, e.g. for top-level constants, functions or types within a file: + +```diff +- fileprivate let someConstant = "someConstant" ++ private let someConstant = "someConstant" +``` + +In Swift 4 and above, `fileprivate` can also be replaced with `private` for members that are only accessed from extensions in the same file: + +```diff + class Foo { +- fileprivate var foo = "foo" ++ private var foo = "foo" + } + + extension Foo { + func bar() { + print(self.foo) + } + } +``` + ***redundantLet*** - removes redundant `let` or `var` from ignored variables in bindings (which is a warning in Xcode): ```diff -- let _ = resultIgnorableFunction() -+ _ = resultIgnorableFunction() -``` - -```diff -- if case (let foo, let _) = bar {} -+ if case (let foo, _) = bar {} -``` - -```diff -- if case .foo(var /* unused */ _) = bar {} -+ if case .foo( /* unused */ _) = bar {} + public extension URL { +- public func queryParameter(_ name: String) -> String { ... } + } + + public extension URL { ++ func queryParameter(_ name: String) -> String { ... } + } ``` ***redundantLetError*** - removes redundant `let error` from `catch` statements, where it is declared implicitly: @@ -700,6 +806,23 @@ let foo: Int? = nil var foo: Int? = 0 ``` +***redundantObjc*** - removes unnecessary `@objc` annotation from properties and functions: + +```diff +- @objc @IBOutlet var label: UILabel! ++ @IBOutlet var label: UILabel! +``` + +```diff +- @IBAction @objc func goBack() {} ++ @IBOutlet func goBack() {} +``` + +```diff +- @objc @NSManaged private var foo: String? ++ @NSManaged private var foo: String? +``` + ***redundantParens*** - removes unnecessary parens from expressions and branch conditions: ```diff @@ -771,6 +894,8 @@ var foo: Int? = 0 } ``` +In the rare case of functions with`@autoclosure` arguments, `self` may be required at the call site, but SwiftFormat is unable to detect this automatically. You can use the `--selfrequired` command-line option to specify a list of such methods, and the `redundantSelf` rule will then ignore them. An example of such a method is the `expect()` function in the [Nimble](https://github.com/Quick/Nimble) unit testing framework, which is common enough that it is excluded by default. + There is also an option to always use explicit `self` but *only* inside `init`, by using `--self init-only`: ```diff @@ -957,7 +1082,7 @@ goto(fail) ***spaceInsideParens*** - removes the space inside `( ... )`: ```diff -- ( a, b ) +- ( a, b) + (a, b) ``` @@ -978,6 +1103,16 @@ goto(fail) + private convenience init() ``` +***strongifiedSelf*** - replaces ``self`` with self when using the common `guard let `self` = self` pattern for strongifying weak self references: + +```diff +- guard let `self` = self else { return } ++ guard let self = self else { return } +``` + +**NOTE:** assignment to un-escaped `self` is only supported in Swift 4.2 and above, so the `strongifiedSelf` rule is disabled unless the [swift version](#swift-version) is set to 4.2 or above. + + ***strongOutlets*** - removes the `weak` specifier from `@IBOutlet` properties, as per [Apple's recommendation](https://developer.apple.com/videos/play/wwdc2015/407/): ```diff @@ -1029,6 +1164,23 @@ goto(fail) + // MARK: - UIScrollViewDelegate ``` +***typeSugar*** - replaces Array, Dictionary and Optional types with their shorthand forms: + +```diff +- var foo: Array ++ var foo: [String] +``` + +```diff +- var foo: Dictionary ++ var foo: [String: Int] +``` + +```diff +- var foo: Optional<(Int) -> Void> ++ var foo: ((Int) -> Void)? +``` + ***unusedArguments*** - marks unused arguments in functions and closures with `_` to make it clear they aren't used. Use the `--stripunusedargs` option to configure which argument types are affected (`always` (default), `closure-only` or `unnamed-only`). ```diff @@ -1064,7 +1216,7 @@ goto(fail) ***void*** - standardizes the use of `Void` vs an empty tuple `()` to represent empty argument lists and return values, depending on the `--empty` option (`void` (default) or `tuple`). ```diff -- let foo: () -> ( +- let foo: () -> () + let foo: () -> Void ``` @@ -1113,31 +1265,21 @@ Or for `--wrapcollections beforefirst`: ] ``` -***andOperator*** - replaces the `&&` operator with `,` inside `if`, `guard` and `while` conditions: -```diff -- if true && true { -+ if true, true { -``` +Swift version +------------- -```diff -- guard true && true else { -+ guard true, true else { -``` +Most SwiftFormat rules are version-agnostic, but a few rules only apply to certain Swift versions. These rules will be disabled automatically if the Swift version is not specified, so to enable them you should specify the version of Swift that is used by your project. -```diff -- if functionReturnsBool() && true { -+ if functionReturnsBool(), true { -``` +You can specify the Swift version one of two ways: -```diff -- if functionReturnsBool() && variable { -+ if functionReturnsBool(), variable { -``` +The preferred option is to add a `.swift-version` file to your project directory. This is a text file that should contain the minimum Swift version supported by your project. This file applies hierarchically. If you have submodules in your project that use a different Swift version, you can add separate `.swift-version` files to those directories. + +The other option to specify the Swift version using the `--swiftversion` command line argument. Note that this will be overridden by any `.swift-version` files encountered while processing. -Config ------- +Config file +----------- Although it is possible to configure SwiftFormat directly by using the command-line [options](#options) and [rules](#rules) detailed above, it is sometimes more convenient to create a configuration file, which can be added to your project and shared with other developers. @@ -1149,11 +1291,17 @@ A SwiftFormat configuration file consists of one or more command-line options, s --disable elseOnSameLine,semicolons ``` -While formatting, SwiftFormat will automatically check inside each subdirectory for the presence of a ".swiftformat" file and will apply any options that it finds there to the files in that directory. +While formatting, SwiftFormat will automatically check inside each subdirectory for the presence of a `.swiftformat` file and will apply any options that it finds there to the files in that directory. -This allows you to override certain rules or formatting options just for a particular directory of files. You can also specify excluded files relative to that directory using `--exclude`, which may be more convenient than specifying them at the top-level. +This allows you to override certain rules or formatting options just for a particular directory of files. You can also specify excluded files relative to that directory using `--exclude`, which may be more convenient than specifying them at the top-level: -Files named ".swiftformat" will be processed automatically, however you can select an additional configuration file to use for formatting using the `--config "path/to/config/file"` command-line argument. A configuration file selected using `--config` does not need to be named ".swiftformat", and can be located outside of the project directory. +``` +--exclude Pods,Generated +``` + +The `--exclude` option takes a comma-delimited list of file or directory paths to exclude from formatting. Excluded paths are relative to the config file containing the `--exclude` command. The excluded paths can include wildcards, specified using Unix "Glob" syntax, as [documented below](#globs). + +Config files named ".swiftformat" will be processed automatically, however you can select an additional configuration file to use for formatting using the `--config "path/to/config/file"` command-line argument. A configuration file selected using `--config` does not need to be named ".swiftformat", and can be located outside of the project directory. The config file format is designed to be human editable. You may include blank lines for readability, and can also add comments using a hash prefix (#), e.g. @@ -1172,22 +1320,57 @@ The config file format is designed to be human editable. You may include blank l If you would prefer not to edit the configuration file by hand, you can use the [SwiftFormat for Xcode](#xcode-source-editor-extension) app to edit the configuration and export a configuration file. Alternatively, you can use the swiftformat command-line-tool's `--inferoptions` command to generate a config file from your existing project, like this: ```bash -> cd /path/to/project -> swiftformat --inferoptions . --output .swiftformat +$ cd /path/to/project +$ swiftformat --inferoptions . --output .swiftformat ``` +Globs +----- + +When excluding files from formatting using the `--exclude` option, you may wish to make use of wildcard paths (aka "Globs") to match all files that match a particular naming convention without having to manually list them all. + +SwiftFormat's glob syntax is based on Ruby's implementation, which varies slightly from the Unix standard. The following patterns are supported: + +* `*` - A single star matches zero or more characters in a filename, but *not* a `/`. + +* `**` - A double star will match anything, including one or more `/`. + +* `?` - A question mark will match any single character except `/`. + +* `[abc]` - Matches any single character inside the brackets. + +* `[a-z]` - Matches a single character in the specified range in the brackets. + +* `{foo,bar}` - Matches any one of the comma-delimited strings inside the braces. + +Examples: + +* `foo.swift` - Matches the file "foo.swift" in the same directory as the config file. + +* `*.swift` - Matches any swift file in the same directory as the config file. + +* `foo/bar.swift` - Matches the file "bar.swift" in the directory "foo". + +* `**/foo.swift` - Matches any file named "foo.swift" in the project. + +* `**/*.swift` - Matches any swift file in the project. + +* `**/Generated` - Matches any folder called `Generated` in the project. + +* `**/*_generated.swift` - Matches any Swift file with the suffix "_generated" in the project. + Linting ------- SwiftFormat is primarily designed as a formatter rather than a linter, i.e. it is designed to fix your code rather than tell you what's wrong with it. However, sometimes it can be useful to verify that code has been formatted in a context where it is not desirable to actually change it. -A typical example would be as part of a CI (Continuous Integration) process, where you may wish to have an automated script that checks committed code for style violations. While you could use a separate tool such as [SwiftLint](https://github.com/realm/SwiftLint) for this, it makes sense to be able to validate the formatting against the exact same rules as you are using to apply it. +A typical example would be as part of a CI (Continuous Integration) process, where you may wish to have an automated script that checks committed code for style violations. While you can use a separate tool such as [SwiftLint](https://github.com/realm/SwiftLint) for this, it makes sense to be able to validate the formatting against the exact same rules as you are using to apply it. In order to run SwiftFormat as a linter, you can use the `--lint` command-line option: ```bash -> swiftformat --lint path/to/project +$ swiftformat --lint path/to/project ``` This works exactly the same way as when running in format mode, and all the same configuration options apply, however no files will be modified. SwiftFormat will simply format each file in memory and then compare the result against the input. If any formatting changes would have been applied, it will report an error. @@ -1197,93 +1380,12 @@ The `--lint` option is very similar to `--dryrun`, except that `--lint` will ret By default, `--lint` will only report the number of files that were changed, but you can use the additional `--verbose` flag to display a detailed report about which specific rules were applied to which specific files. -FAQ ------ - -There haven't been many questions yet, but here's what I'd like to think people are wondering: - - -*Q. What versions of Swift are supported?* - -> A. The framework compiles on Swift 3.x or 4.x and can format programs written in Swift 3.x or 4.x. Swift 2.x is no longer actively supported. If you are still using Swift 2.x, and find that SwiftFormat breaks your code, the best solution is probably to revert to an earlier SwiftFormat release, or enable only a small subset of rules. - - -*Q. I don't like how SwiftFormat formatted my code* - -> A. That's not a question (but see below). - - -*Q. How can I modify the formatting rules?* - -> A. Many configuration options are exposed in the command-line interface or .swiftformat configuration file. You can either set these manually, or use the `--inferoptions` argument to automatically generate the configuration from your existing project. - -> If there is a rule that you don't like, and which cannot be configured to your liking via the command-line options, you can disable the rule by using the `--disable` argument, followed by the name of the rule. You can display a list of all rules using the `--rules` argument, and their behaviors are documented above this section in the README. - -> If you are using the Xcode source editor extension, rules and options can be configured using the [SwiftFormat for Xcode](#xcode-source-editor-extension) host application. Unfortunately, due to limitation of the Extensions API, there is no way to configure these on a per-project basis. - -> If the options you want aren't exposed, and disabling the rule doesn't solve the problem, the rules are implemented as functions in the file `Rules.swift`, so you can modify them and build a new version of the command-line tool. If you think your changes might be generally useful, make a pull request. - - -*Q. Why can't I set the indent width or choose between tabs/spaces in the [SwiftFormat for Xcode](#xcode-source-editor-extension) options?* - -> Indent width and tabs/spaces can be configured in Xcode on a per project-basis. You'll find the option under "Text Settings" in the right-hand sidebar. - - -*Q. After applying SwiftFormat, my code won't compile. Is that a bug?* - -> A. SwiftFormat should never break your code. Check the known issues below, and if it's not already listed there, or the suggested workaround doesn't solve your problem, please [raise an issue on Github](https://github.com/nicklockwood/SwiftFormat/issues). - - -*Q. Why did you write yet another Swift formatting tool?* - -> A. Surprisingly, there really aren't that many other options out there, and none of them currently support all the rules I wanted. The only other comparable ones I'm aware of are Realm's [SwiftLint](https://github.com/realm/SwiftLint) and Jintin's [Swimat](https://github.com/Jintin/Swimat) - you might want to try those if SwiftFormat doesn't meet your requirements. - - -*Q. Does it use SourceKit?* - -> A. No. - - -*Q. Why would you write a parser from scratch instead of just using SourceKit?* - -> A. The fact that there aren't already dozens of full-featured Swift formatters using SourceKit would suggest that the "just" isn't warranted. - - -*Q. You wrote a Swift parser from scratch!? Are you a wizard?* - -> A. Yes. Yes I am. - - -*Q. How does it work?* - -> A. First it loops through the source file character-by-character and breaks it into tokens, such as `number`, `identifier`, `linebreak`, etc. That's handled by the functions in `Tokenizer.swift`. - -> Next, it applies a series of formatting rules to the token array, such as removing whitespace at the end of a line, or ensuring each opening brace appears on the same line as the preceding non-space token. The rules are defined as methods of the `FormatRules` class in `Rules.swift`, and are detected automatically using runtime magic. Each rule is designed to be independent of the others, so they can be enabled or disabled individually. - -> Rules are applied recursively until no changes are detected. Finally, the modified token array is stitched back together to re-generate the source file. - - -*Q. Why aren't you using regular expressions?* - -> A. See https://xkcd.com/1171/ for details. - - -*Q. Can I use SwiftFormat to lint my code without changing it?* - -> A. Yes, see the [linting](#linting) section above for details. - - -*Q. Can I use the `SwiftFormat.framework` inside another app?* - -> A. Yes, the SwiftFormat framework can be included in an app or test target, and used for many kinds of parsing and processing of Swift source code besides formatting. The SwiftFormat framework is available as a [CocoaPod](https://cocoapods.org/pods/SwiftFormat) for easy integration. - - Cache ------ SwiftFormat uses a cache file to avoid reformatting files that haven't changed. For a large project, this can significantly reduce processing time. -By default, the cache is stored in `~/Library/Caches/com.charcoaldesign.swiftformat`. Use the command-line option `--cache ignore` to ignore the cached version and re-apply formatting to all files. Alternatively, you can use `--cache clear` to delete the cache (or you can just manually delete the cache file). +By default, the cache is stored in `~/Library/Caches/com.charcoaldesign.swiftformat` on macOS, or `/var/tmp/com.charcoaldesign.swiftformat` on Linux. Use the command-line option `--cache ignore` to ignore the cached version and re-apply formatting to all files. Alternatively, you can use `--cache clear` to delete the cache (or you can just manually delete the cache file). The cache is shared between all projects. The file is fairly small, as it only stores the path and size for each file, not the contents. If you do start experiencing slowdown due to the cache growing too large, you might want to consider using a separate cache file for each project. @@ -1314,19 +1416,93 @@ You can optionally include Swift comment markup in the template if you wish: `-- If you do not include comment markup, each line in the template will be prepended with `//` and a single space. -Finally, it is common practice to include the current year in a comment header copyright notice. To do that, use the following syntax: +It is common practice to include the file name, creation date and/or the current year in a comment header copyright notice. To do that, you can use the following placeholders: + +* `{file}` - the name of the file +* `{year}` - the current year +* `{created}` - the date on which the file was created +* `{created.year}` - the year in which the file was created + +For example, a header template of: ```bash ---header "Copyright (c) {year} Foobar Industries" +--header "{file}\nCopyright (c) {year} Foobar Industries\nCreated by John Smith on {created}." ``` - -And the `{year}` token will be automatically replaced by the current year whenever SwiftFormat is applied (**Note:** the year is determined from the locale and timezone of the machine running the script). + +Will be formatted as: + +```swift +// SomeFile.swift +// Copyright (c) 2019 Foobar Industries +// Created by John Smith on 01/02/2016. +``` + +**NOTE:** the `{year}` value and `{created}` date format are determined from the current locale and timezone of the machine running the script. + + +FAQ +----- + +*Q. How is this different from SwiftLint?* + +> A. SwiftLint is primarily designed to find and report code smells and style violations in your code. SwiftFormat is designed to fix them. While SwiftLint can autocorrect some issues, and SwiftFormat has some support for [linting](#linting), their primary goals are different. + + +*Q. Can SwiftFormat and SwiftLint be used together?* + +> A. Absolutely! The style rules encouraged by both tools are quite similar, and SwiftFormat even fixes some style violations that SwiftLint warns about, but can't currently autocorrect. + + +*Q. What platforms does SwiftFormat support?* + +> A. Swiftformat works on macOS 10.12 (Sierra) and above, and also runs on Ubuntu Linux. + + +*Q. What versions of Swift are supported?* + +> A. The SwiftFormat framework and command-line tool can be compiled using Swift 4.0 and above, and can format programs written in Swift 3.x or 4.x. Swift 2.x is no longer actively supported. If you are still using Swift 2.x, and find that SwiftFormat breaks your code, the best solution is probably to revert to an earlier SwiftFormat release, or enable only a small subset of rules. + + +*Q. SwiftFormat made changes I didn't want it to. How can I find out which rules to disable?* + +> A. If you run SwiftFormat using the `--verbose` option, it will tell you which rules were applied to each file. You can then selectively disable certain rules using the `--disable` argument (see below). + + +*Q. How can I modify the formatting rules?* + +> A. Many configuration options are exposed in the command-line interface or `.swiftformat` configuration file. You can either set these manually, or use the `--inferoptions` argument to automatically generate the configuration from your existing project. + +> If there is a rule that you don't like, and which cannot be configured to your liking via the command-line options, you can disable one or more rules by using the `--disable` argument, followed by the name of the rules, separated by commas. You can display a list of all supported rules using the `--rules` argument, and their behaviors are documented above this section in the README. + +> If you are using the Xcode source editor extension, rules and options can be configured using the [SwiftFormat for Xcode](#xcode-source-editor-extension) host application. Unfortunately, due to limitation of the Extensions API, there is no way to configure these on a per-project basis. + +> If the options you want aren't exposed, and disabling the rule doesn't solve the problem, the rules are implemented in the file `Rules.swift`, so you can modify them and build a new version of the command-line tool. If you think your changes might be generally useful, make a pull request. + + +*Q. Why can't I set the indent width or choose between tabs/spaces in the [SwiftFormat for Xcode](#xcode-source-editor-extension) options?* + +> Indent width and tabs/spaces can be configured in Xcode on a per project-basis. You'll find the option under "Text Settings" in the right-hand sidebar. + + +*Q. After applying SwiftFormat, my code won't compile. Is that a bug?* + +> A. SwiftFormat should ideally never break your code. Check the known issues below, and if it's not already listed there, or the suggested workaround doesn't solve your problem, please [raise an issue on Github](https://github.com/nicklockwood/SwiftFormat/issues). + + +*Q. Can I use SwiftFormat to lint my code without changing it?* + +> A. Yes, see the [linting](#linting) section above for details. + + +*Q. Can I use the `SwiftFormat.framework` inside another app?* + +> A. Yes, the SwiftFormat framework can be included in an app or test target, and used for many kinds of parsing and processing of Swift source code besides formatting. The SwiftFormat framework is available as a [CocoaPod](https://cocoapods.org/pods/SwiftFormat) for easy integration. Known issues --------------- -* When using the `--self remove` option, the `redundantSelf` rule will remove references to `self` in autoclosure arguments, which may change the meaning of the code, or cause it not to compile. To work around this issue, use the `// swiftformat:disable:next redundantSelf` comment directive to disable the rule for any affected lines of code (or just disable the `redundantSelf` rule completely). If you are using the `--self insert` option then this is not an issue. +* When using the `--self remove` option, the `redundantSelf` rule will remove references to `self` in autoclosure arguments, which may change the meaning of the code, or cause it not to compile. To work around this issue, use the `--selfrequired` option to provide a comma-delimited list of methods to be excluded from the rule. The `expect()` function from the popular [Nimble](https://github.com/Quick/Nimble) unit testing framework is already excluded by default. If you are using the `--self insert` option then this is not an issue. * If you assign `SomeClass.self` to a variable and then instantiate an instance of the class using that variable, Swift requires that you use an explicit `.init()`, however the `redundantInit` rule is not currently capable of detecting this situation and will remove the `.init`. To work around this issue, use the `// swiftformat:disable:next redundantInit` comment directive to disable the rule for any affected lines of code (or just disable the `redundantInit` rule completely). @@ -1334,6 +1510,8 @@ Known issues * The `trailingClosures` rule will sometimes generate ambiguous code that breaks your program. For this reason, the rule is disabled by default. It is recommended that you apply this rule manually and review the changes, rather than including it in an automated formatting process. +* The `isEmpty` rule will convert `count == 0` to `isEmpty` even for types that do not have an `isEmpty` method, such as `NSArray`/`NSDictionary`/etc. Use of Objective-C collections in Swift code is pretty rare however, as the Swift-ObjC bridge converts them automatically. + * Under rare circumstances, SwiftFormat may misinterpret a generic type followed by an `=` sign as a pair of `<` and `>=` expressions. For example, the following case would be handled incorrectly: ```swift @@ -1347,7 +1525,7 @@ Known issues let foo: Dictionary=["Hello": "World"] ``` -* If a file begins with a comment, the `stripHeaders` rule will remove it if is followed by a blank line. To avoid this, make sure that the first comment is directly followed by a line of code. +* If a file begins with a comment, the `stripHeaders` rule will remove it if it is followed by a blank line. To avoid this, make sure that the first comment is directly followed by a line of code. * SwiftFormat currently reformats multiline comment blocks without regard for the original indenting. That means @@ -1402,6 +1580,8 @@ Known issues * The formatted file cache is based on a hash of the file contents, so it's possible (though unlikely) that an edited file will have the exact same hash as the previously formatted version, causing SwiftFormat to incorrectly identify it as not having changed, and fail to update it. To fix this, you can use the command-line option `--cache ignore` to force SwiftFormat to ignore the cache for this run, or just type an extra space in the file (which SwiftFormat will then remove again when it applies the correct formatting). + +* When running on Linux, the `--symlinks` option has no effect. Credits @@ -1413,6 +1593,7 @@ Credits * [Romain Pouclet](https://github.com/palleas) - Homebrew formula * [Ali Akhtarzada](https://github.com/aliak00) - Several path-related CLI enhancements * [Yonas Kolb](https://github.com/yonaskolb) - Swift Package Manager integration +* [Wolfgang Lutz](https://github.com/Lutzifer) - AppleScript integration instructions * [Nick Lockwood](https://github.com/nicklockwood) - Everything else ([Full list of contributors](https://github.com/nicklockwood/SwiftFormat/graphs/contributors)) diff --git a/Example/Pods/SwiftLint/swiftlint b/Example/Pods/SwiftLint/swiftlint index d5ea1b2..0dc9703 100755 Binary files a/Example/Pods/SwiftLint/swiftlint and b/Example/Pods/SwiftLint/swiftlint differ diff --git a/Example/Pods/Target Support Files/GradientLoadingBar/GradientLoadingBar.xcconfig b/Example/Pods/Target Support Files/GradientLoadingBar/GradientLoadingBar.xcconfig index 83b41ad..e5f10c9 100644 --- a/Example/Pods/Target Support Files/GradientLoadingBar/GradientLoadingBar.xcconfig +++ b/Example/Pods/Target Support Files/GradientLoadingBar/GradientLoadingBar.xcconfig @@ -1,5 +1,4 @@ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Observable" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" PODS_BUILD_DIR = ${BUILD_DIR} diff --git a/Example/Pods/Target Support Files/Observable/Info.plist b/Example/Pods/Target Support Files/Observable/Info.plist deleted file mode 100644 index 7b6b52a..0000000 --- a/Example/Pods/Target Support Files/Observable/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.4.0 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - - diff --git a/Example/Pods/Target Support Files/Observable/Observable-dummy.m b/Example/Pods/Target Support Files/Observable/Observable-dummy.m deleted file mode 100644 index 5bd8d5a..0000000 --- a/Example/Pods/Target Support Files/Observable/Observable-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Observable : NSObject -@end -@implementation PodsDummy_Observable -@end diff --git a/Example/Pods/Target Support Files/Observable/Observable-prefix.pch b/Example/Pods/Target Support Files/Observable/Observable-prefix.pch deleted file mode 100644 index beb2a24..0000000 --- a/Example/Pods/Target Support Files/Observable/Observable-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/Example/Pods/Target Support Files/Observable/Observable-umbrella.h b/Example/Pods/Target Support Files/Observable/Observable-umbrella.h deleted file mode 100644 index ef9454c..0000000 --- a/Example/Pods/Target Support Files/Observable/Observable-umbrella.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - - -FOUNDATION_EXPORT double ObservableVersionNumber; -FOUNDATION_EXPORT const unsigned char ObservableVersionString[]; - diff --git a/Example/Pods/Target Support Files/Observable/Observable.modulemap b/Example/Pods/Target Support Files/Observable/Observable.modulemap deleted file mode 100644 index b7db007..0000000 --- a/Example/Pods/Target Support Files/Observable/Observable.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module Observable { - umbrella header "Observable-umbrella.h" - - export * - module * { export * } -} diff --git a/Example/Pods/Target Support Files/Observable/Observable.xcconfig b/Example/Pods/Target Support Files/Observable/Observable.xcconfig deleted file mode 100644 index 53a839a..0000000 --- a/Example/Pods/Target Support Files/Observable/Observable.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Observable -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/Observable -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-acknowledgements.markdown index c855ef2..cfbd4b5 100644 --- a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-acknowledgements.markdown +++ b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-acknowledgements.markdown @@ -24,32 +24,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -## Observable - - -MIT License - -Copyright (c) 2017 Robert-Hein Hooijmans - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - ## SwiftFormat MIT License diff --git a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-acknowledgements.plist index 610c2bd..4892f3b 100644 --- a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-acknowledgements.plist +++ b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-acknowledgements.plist @@ -41,38 +41,6 @@ THE SOFTWARE. Type PSGroupSpecifier - - FooterText - -MIT License - -Copyright (c) 2017 Robert-Hein Hooijmans <rh.hooijmans@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - License - MIT - Title - Observable - Type - PSGroupSpecifier - FooterText MIT License diff --git a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-frameworks.sh b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-frameworks.sh index ce007b5..55fc4c5 100755 --- a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-frameworks.sh +++ b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-frameworks.sh @@ -144,11 +144,9 @@ strip_invalid_archs() { if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/GradientLoadingBar/GradientLoadingBar.framework" - install_framework "${BUILT_PRODUCTS_DIR}/Observable/Observable.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/GradientLoadingBar/GradientLoadingBar.framework" - install_framework "${BUILT_PRODUCTS_DIR}/Observable/Observable.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait diff --git a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.debug.xcconfig b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.debug.xcconfig index a791954..cba8145 100644 --- a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.debug.xcconfig +++ b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.debug.xcconfig @@ -1,9 +1,9 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar" "${PODS_CONFIGURATION_BUILD_DIR}/Observable" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar/GradientLoadingBar.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Observable/Observable.framework/Headers" -OTHER_LDFLAGS = $(inherited) -framework "GradientLoadingBar" -framework "Observable" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar/GradientLoadingBar.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "GradientLoadingBar" OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.release.xcconfig b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.release.xcconfig index a791954..cba8145 100644 --- a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.release.xcconfig +++ b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.release.xcconfig @@ -1,9 +1,9 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar" "${PODS_CONFIGURATION_BUILD_DIR}/Observable" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar/GradientLoadingBar.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Observable/Observable.framework/Headers" -OTHER_LDFLAGS = $(inherited) -framework "GradientLoadingBar" -framework "Observable" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar/GradientLoadingBar.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "GradientLoadingBar" OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.debug.xcconfig b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.debug.xcconfig index 4f38a8a..1957af0 100644 --- a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.debug.xcconfig +++ b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.debug.xcconfig @@ -1,7 +1,7 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar" "${PODS_CONFIGURATION_BUILD_DIR}/Observable" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar/GradientLoadingBar.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Observable/Observable.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar/GradientLoadingBar.framework/Headers" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.release.xcconfig b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.release.xcconfig index 4f38a8a..1957af0 100644 --- a/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.release.xcconfig +++ b/Example/Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.release.xcconfig @@ -1,7 +1,7 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar" "${PODS_CONFIGURATION_BUILD_DIR}/Observable" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar/GradientLoadingBar.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Observable/Observable.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar/GradientLoadingBar.framework/Headers" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/Example/Tests/ViewModel/GradientLoadingBarViewModelTestCase.swift b/Example/Tests/Feature/GradientLoadingBar/GradientLoadingBarViewModelTestCase.swift similarity index 98% rename from Example/Tests/ViewModel/GradientLoadingBarViewModelTestCase.swift rename to Example/Tests/Feature/GradientLoadingBar/GradientLoadingBarViewModelTestCase.swift index 3b8964e..e9d334d 100644 --- a/Example/Tests/ViewModel/GradientLoadingBarViewModelTestCase.swift +++ b/Example/Tests/Feature/GradientLoadingBar/GradientLoadingBarViewModelTestCase.swift @@ -7,7 +7,6 @@ // import XCTest -import Observable @testable import GradientLoadingBar @@ -100,15 +99,15 @@ class GradientLoadingBarViewModelTestCase: XCTestCase { var observerCounter = 0 - var disposal = Disposal() - viewModel.superview.observe { newSuperview, _ in + var disposeBag = DisposeBag() + viewModel.superview.subscribe { newSuperview, _ in guard newSuperview != nil else { // Skip initial call to observer. return } observerCounter += 1 - }.add(to: &disposal) + }.add(to: &disposeBag) // When for _ in 1 ... 3 { diff --git a/Example/Tests/Feature/Observable/DisposableTestCase.swift b/Example/Tests/Feature/Observable/DisposableTestCase.swift new file mode 100644 index 0000000..4c1b84a --- /dev/null +++ b/Example/Tests/Feature/Observable/DisposableTestCase.swift @@ -0,0 +1,52 @@ +// +// DisposableTestCase.swift +// GradientLoadingBar_Tests +// +// Created by Felix Mau on 11/02/19. +// Copyright © 2019 Felix Mau. All rights reserved. +// + +import XCTest + +@testable import GradientLoadingBar + +class DisposableTestCase: XCTestCase { + func testDisposeClosureShouldNotBeCalledBeforeDeinit() { + // Given + let expectation = self.expectation(description: "Expect dispose closure not to be called.") + expectation.isInverted = true + + var disposable: Disposable? + disposable = Disposable { + expectation.fulfill() + } + + // Workaround to fix warning `Variable 'disposable' was written to, but never read` + XCTAssertNotNil(disposable, "Precondition failed - Expected to have a valid instance at this point.") + + // When + // ... + + // Then + wait(for: [expectation], timeout: 1.0) + } + + func testDisposeClosureShouldBeCalledOnDeinit() { + // Given + let expectation = self.expectation(description: "Expect dispose closure to be called on deinit.") + + var disposable: Disposable? + disposable = Disposable { + expectation.fulfill() + } + + // Workaround to fix warning `Variable 'disposable' was written to, but never read` + XCTAssertNotNil(disposable, "Precondition failed - Expected to have a valid instance at this point.") + + // When + disposable = nil + + // Then + wait(for: [expectation], timeout: 0.1) + } +} diff --git a/Example/Tests/Feature/Observable/ObservableTestCase.swift b/Example/Tests/Feature/Observable/ObservableTestCase.swift new file mode 100644 index 0000000..3ac3b2c --- /dev/null +++ b/Example/Tests/Feature/Observable/ObservableTestCase.swift @@ -0,0 +1,192 @@ +// +// ObservableTestCase.swift +// GradientLoadingBar_Tests +// +// Created by Felix Mau on 11/02/19. +// Copyright © 2019 Felix Mau. All rights reserved. +// + +import XCTest + +@testable import GradientLoadingBar + +class ObservableTestCase: XCTestCase { + // MARK: - Private properties + + private var disposeBag: DisposeBag! + + private var oldValue: Int? + private var newValue: Int? + + // MARK: - Public methods + + override func setUp() { + super.setUp() + + disposeBag = DisposeBag() + + oldValue = nil + newValue = nil + } + + override func tearDown() { + disposeBag = nil + + super.tearDown() + } + + // MARK: - Test method `observe(:)` + + func testObservableShouldInformObserverWithCorrectValues() { + // Given + let variable = Variable(0) + + // When + variable.asObservable.subscribe { newValue, oldValue in + self.newValue = newValue + self.oldValue = oldValue + }.add(to: &disposeBag) + + // Then + XCTAssertEqual(newValue, 0) + XCTAssertNil(oldValue) + } + + func testObservableShouldUpdateObserverWithCorrectValues() { + // Given + let variable = Variable(0) + + variable.asObservable.subscribe { newValue, oldValue in + self.newValue = newValue + self.oldValue = oldValue + }.add(to: &disposeBag) + + // When + for value in 1 ..< 10 { + variable.value = value + + // Then + XCTAssertEqual(newValue, value) + XCTAssertEqual(oldValue, value - 1) + } + } + + // MARK: - Test method `observe(filter:)` + + func testObservableShouldUpdateObserverOnlyIfFilterMatches() { + // Given + let assertNewValueIsEven: (Int, Int?) -> Bool = { newValue, _ in + newValue.isEven + } + + let expectation = self.expectation(description: "Expected five even numbers between `0` and `9`.") + expectation.expectedFulfillmentCount = 5 + + let variable = Variable(0) + variable.asObservable.subscribe(filter: assertNewValueIsEven, observer: { newValue, _ in + guard newValue.isEven else { + XCTFail("The received value `\(newValue)` is odd!") + return + } + + expectation.fulfill() + }).add(to: &disposeBag) + + // When + for value in 1 ..< 10 { + variable.value = value + } + + // Then + waitForExpectations(timeout: 0.1, handler: nil) + } + + // MARK: - Test method `observeDistinct(:)` + + func testObservableShouldInformDistinctObserverWithCorrectValues() { + // Given + let variable = Variable(0) + + // When + variable.asObservable.subscribeDistinct { newValue, oldValue in + self.newValue = newValue + self.oldValue = oldValue + }.add(to: &disposeBag) + + // Then + XCTAssertEqual(newValue, 0) + XCTAssertNil(oldValue) + } + + func testObservableShouldUpdateDistinctObserverWithCorrectValues() { + // Given + let variable = Variable(0) + + variable.asObservable.subscribeDistinct { newValue, oldValue in + self.newValue = newValue + self.oldValue = oldValue + }.add(to: &disposeBag) + + // When + for value in 1 ..< 10 { + variable.value = value + + // Then + XCTAssertEqual(newValue, value) + XCTAssertEqual(oldValue, value - 1) + } + } + + func testObservableShouldUpdateDistinctObserverJustOnceForSameValue() { + // Given + let expectation = self.expectation(description: "Expected distinct observer to be informed two times: The inital call and the new value.") + expectation.expectedFulfillmentCount = 2 + + let variable = Variable(0) + variable.asObservable.subscribeDistinct { newValue, oldValue in + self.newValue = newValue + self.oldValue = oldValue + + expectation.fulfill() + }.add(to: &disposeBag) + + // When + for _ in 1 ..< 10 { + variable.value = 1 + + // Then + XCTAssertEqual(newValue, 1) + XCTAssertEqual(oldValue, 0) + } + + waitForExpectations(timeout: 0.1, handler: nil) + } + + // MARK: - Test deallocated dispose bag + + func testObservableShouldNotInformObserverAfterDeallocatedDisposeBag() { + // Given + let variable = Variable(0) + + variable.asObservable.subscribe { newValue, oldValue in + self.newValue = newValue + self.oldValue = oldValue + }.add(to: &disposeBag) + + // When + disposeBag = nil + variable.value = 1 + + // Then + XCTAssertEqual(newValue, 0) + XCTAssertNil(oldValue) + } +} + +// MARK: - Helpers + +private extension Int { + var isEven: Bool { + return self % 2 == 0 + } +} diff --git a/Example/Tests/Helpers/Extensions/Observable+ObserveDistinctTestCase.swift b/Example/Tests/Helpers/Extensions/Observable+ObserveDistinctTestCase.swift deleted file mode 100644 index 40b4424..0000000 --- a/Example/Tests/Helpers/Extensions/Observable+ObserveDistinctTestCase.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// Observable+ObserveDistinctTestCase.swift -// GradientLoadingBar_Tests -// -// Created by Felix Mau on 08/25/18. -// Copyright © 2018 Felix Mau. All rights reserved. -// - -import XCTest -import Observable - -class ObservableObserveDistinctTestCase: XCTestCase { - func testObserveDistinctShouldNotifyListener() { - // Given - let prevValue = 123 - let nextValue = 456 - - let observable = Observable(prevValue) - - var observeCallCounter = 0 - - var disposeBag = Disposal() - observable.observeDistinct { _, _ in - observeCallCounter += 1 - }.add(to: &disposeBag) - - // When - observable.value = nextValue - - // Then - XCTAssertEqual(observeCallCounter, 2) - } - - func testObserveDistinctShouldNotNotifyListenerDueToSameValue() { - // Given - let prevValue = 123 - let nextValue = 123 - - let observable = Observable(prevValue) - - var observeCallCounter = 0 - - var disposeBag = Disposal() - observable.observeDistinct { _, _ in - observeCallCounter += 1 - }.add(to: &disposeBag) - - // When - observable.value = nextValue - - // Then - XCTAssertEqual(observeCallCounter, 1) - } -} diff --git a/GradientLoadingBar.podspec b/GradientLoadingBar.podspec index 78238ed..d6a5fe0 100644 --- a/GradientLoadingBar.podspec +++ b/GradientLoadingBar.podspec @@ -41,5 +41,4 @@ Inspired by https://codepen.io/marcobiedermann/pen/LExXWW # s.frameworks = 'UIKit', 'MapKit' # s.dependency 'AFNetworking', '~> 2.3' - s.dependency 'Observable', '~> 1.4' end diff --git a/GradientLoadingBar/Classes/Extensions/ImmutableObservable/ImmutableObservable+ObserveDistinct.swift b/GradientLoadingBar/Classes/Extensions/ImmutableObservable/ImmutableObservable+ObserveDistinct.swift deleted file mode 100644 index a7fb613..0000000 --- a/GradientLoadingBar/Classes/Extensions/ImmutableObservable/ImmutableObservable+ObserveDistinct.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// ImmutableObservable+ObserveDistinct.swift -// GradientLoadingBar -// -// Created by Felix Mau on 08/25/18. -// Copyright © 2018 Felix Mau. All rights reserved. -// - -import Foundation -import Observable - -extension ImmutableObservable where T: Equatable { - /// A wrapper around the `observe` method, that checks whether the previous value is different from the next value. - /// If they are equal the listener will not be notified. This is useful to prevent unnecessary UI updates. - public func observeDistinct(_ observer: @escaping Observer) -> Disposable { - return observe { nextValue, prevValue in - guard nextValue != prevValue else { return } - - observer(nextValue, prevValue) - } - } -} diff --git a/GradientLoadingBar/Classes/Extensions/UIView/UIView+AnimateIsHidden.swift b/GradientLoadingBar/Classes/Extensions/UIView/UIView+AnimateIsHidden.swift index fd5791e..70756ae 100644 --- a/GradientLoadingBar/Classes/Extensions/UIView/UIView+AnimateIsHidden.swift +++ b/GradientLoadingBar/Classes/Extensions/UIView/UIView+AnimateIsHidden.swift @@ -8,7 +8,9 @@ import UIKit -/// Source: https://gist.github.com/fxm90/723b5def31b46035cd92a641e3b184f6 +// Source +// https://gist.github.com/fxm90/723b5def31b46035cd92a641e3b184f6 + extension UIView { // MARK: - Config diff --git a/GradientLoadingBar/Classes/BottomGradientLoadingBarController.swift b/GradientLoadingBar/Classes/Feature/GradientLoadingBar/BottomGradientLoadingBarController.swift similarity index 100% rename from GradientLoadingBar/Classes/BottomGradientLoadingBarController.swift rename to GradientLoadingBar/Classes/Feature/GradientLoadingBar/BottomGradientLoadingBarController.swift diff --git a/GradientLoadingBar/Classes/GradientLoadingBarController.swift b/GradientLoadingBar/Classes/Feature/GradientLoadingBar/GradientLoadingBarController.swift similarity index 95% rename from GradientLoadingBar/Classes/GradientLoadingBarController.swift rename to GradientLoadingBar/Classes/Feature/GradientLoadingBar/GradientLoadingBarController.swift index d493943..5ece104 100644 --- a/GradientLoadingBar/Classes/GradientLoadingBarController.swift +++ b/GradientLoadingBar/Classes/Feature/GradientLoadingBar/GradientLoadingBarController.swift @@ -6,7 +6,6 @@ // Copyright © 2016 Felix Mau. All rights reserved. // -import Observable import UIKit /// Typealias for controller to match pod name. @@ -36,7 +35,7 @@ open class GradientLoadingBarController { private let viewModel: GradientLoadingBarViewModel /// The dispose bag for the observables. - private var disposal = Disposal() + private var disposeBag = DisposeBag() // MARK: - Initializers @@ -82,14 +81,14 @@ open class GradientLoadingBarController { } private func bindViewModelToView() { - viewModel.animatedVisibilityUpdate.observeDistinct { [weak self] newAnimatedVisibilityUpdate, _ in + viewModel.animatedVisibilityUpdate.subscribeDistinct { [weak self] newAnimatedVisibilityUpdate, _ in self?.gradientView.animate(isHidden: newAnimatedVisibilityUpdate.isHidden, duration: newAnimatedVisibilityUpdate.duration) - }.add(to: &disposal) + }.add(to: &disposeBag) - viewModel.superview.observeDistinct { [weak self] newSuperview, _ in + viewModel.superview.subscribeDistinct { [weak self] newSuperview, _ in self?.addGradientView(to: newSuperview) - }.add(to: &disposal) + }.add(to: &disposeBag) } private func addGradientView(to superview: UIView?) { diff --git a/GradientLoadingBar/Classes/Structs/Durations.swift b/GradientLoadingBar/Classes/Feature/GradientLoadingBar/Structs/Durations.swift similarity index 100% rename from GradientLoadingBar/Classes/Structs/Durations.swift rename to GradientLoadingBar/Classes/Feature/GradientLoadingBar/Structs/Durations.swift diff --git a/GradientLoadingBar/Classes/ViewModel/GradientLoadingBarViewModel.swift b/GradientLoadingBar/Classes/Feature/GradientLoadingBar/ViewModel/GradientLoadingBarViewModel.swift similarity index 89% rename from GradientLoadingBar/Classes/ViewModel/GradientLoadingBarViewModel.swift rename to GradientLoadingBar/Classes/Feature/GradientLoadingBar/ViewModel/GradientLoadingBarViewModel.swift index 3e43c57..e56e441 100644 --- a/GradientLoadingBar/Classes/ViewModel/GradientLoadingBarViewModel.swift +++ b/GradientLoadingBar/Classes/Feature/GradientLoadingBar/ViewModel/GradientLoadingBarViewModel.swift @@ -7,7 +7,6 @@ // import Foundation -import Observable /// The `GradientLoadingBarViewModel` class is responsible for the visibility state of the gradient view. class GradientLoadingBarViewModel { @@ -29,20 +28,20 @@ class GradientLoadingBarViewModel { // MARK: - Public properties /// Observable for animated visibility updates for the gradient-view. - var animatedVisibilityUpdate: ImmutableObservable { - return animatedVisibilityUpdateSubject + var animatedVisibilityUpdate: Observable { + return animatedVisibilityUpdateSubject.asObservable } /// Observable for the superview of the gradient-view. - var superview: ImmutableObservable { - return superviewSubject + var superview: Observable { + return superviewSubject.asObservable } // MARK: - Private properties - private let animatedVisibilityUpdateSubject: Observable = Observable(.immediatelyHidden) + private let animatedVisibilityUpdateSubject: Variable = Variable(.immediatelyHidden) - private let superviewSubject: Observable = Observable(nil) + private let superviewSubject: Variable = Variable(nil) /// Configuration with durations for fade-in / fade-out animations. private let durations: Durations @@ -84,7 +83,7 @@ class GradientLoadingBarViewModel { @objc private func didReceiveUIWindowDidBecomeKeyNotification(_: Notification) { guard let keyWindow = sharedApplication.keyWindow else { return } - // Prevent informing the listeners multiple times. + // Prevent informing the listener multiple times. notificationCenter.removeObserver(self) // Now that we have a valid key window, we can use it as superview. diff --git a/GradientLoadingBar/Classes/Views/GradientView.swift b/GradientLoadingBar/Classes/Feature/GradientLoadingBar/Views/GradientView.swift similarity index 100% rename from GradientLoadingBar/Classes/Views/GradientView.swift rename to GradientLoadingBar/Classes/Feature/GradientLoadingBar/Views/GradientView.swift diff --git a/GradientLoadingBar/Classes/Feature/Observable/Disposable.swift b/GradientLoadingBar/Classes/Feature/Observable/Disposable.swift new file mode 100644 index 0000000..6a8a9bc --- /dev/null +++ b/GradientLoadingBar/Classes/Feature/Observable/Disposable.swift @@ -0,0 +1,41 @@ +// +// Disposable.swift +// GradientLoadingBar +// +// Created by Felix Mau on 11/02/19. +// Copyright © 2019 Felix Mau. All rights reserved. +// + +import Foundation + +// Source +// https://gist.github.com/fxm90/26357043cfe174fabdeedd07d0f25314 + +/// Helper to allow storing multiple disposables (and matching name from RxSwift). +typealias DisposeBag = [Disposable] + +final class Disposable { + // MARK: - Types + + typealias Dispose = () -> Void + + // MARK: - Private properties + + private let dispose: Dispose + + // MARK: - Initializer + + init(_ dispose: @escaping Dispose) { + self.dispose = dispose + } + + deinit { + dispose() + } + + // MARK: - Public methods + + func add(to disposeBag: inout DisposeBag) { + disposeBag.append(self) + } +} diff --git a/GradientLoadingBar/Classes/Feature/Observable/Observable.swift b/GradientLoadingBar/Classes/Feature/Observable/Observable.swift new file mode 100644 index 0000000..e09a00c --- /dev/null +++ b/GradientLoadingBar/Classes/Feature/Observable/Observable.swift @@ -0,0 +1,129 @@ +// +// Observable.swift +// GradientLoadingBar +// +// Created by Felix Mau on 11/02/19. +// Copyright © 2019 Felix Mau. All rights reserved. +// + +import Foundation + +// Source +// https://gist.github.com/fxm90/26357043cfe174fabdeedd07d0f25314 + +class Observable { + // MARK: - Types + + typealias Index = UInt + + typealias NewValue = T + + typealias OldValue = T? + + typealias Observer = (NewValue, OldValue) -> Void + + // MARK: - Public properties + + /// The current (readonly) value of the observable. + 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) { + 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. + 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 when it's deallocated. + return Disposable { [weak self] in + self?.observers[currentIndex] = nil + } + } +} + +extension Observable where T: Equatable { + // MARK: - Types + + typealias Filter = (NewValue, OldValue) -> Bool + + // MARK: - Public methods + + /// Informs the given observer on changes to our `value`, if the given filter matches. + /// + /// - Parameters: + /// - 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 } + + observer(nextValue, prevValue) + } + } + + /// Informs the given observer on **distinct** changes to our `value`. + /// + /// - Parameter observer: The observer-closure that is notified on changes. + func subscribeDistinct(_ observer: @escaping Observer) -> Disposable { + return subscribe(filter: { $0 != $1 }, + observer: observer) + } +} + +final class Variable: Observable { + // MARK: - Public properties + + /// The current variable converted to an (readonly) `Observable`. + var asObservable: Observable { + return self as Observable + } + + /// The current value of the observable. + 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. + override init(_ value: T) { + super.init(value) + } +} diff --git a/readme.md b/readme.md index b817da2..51e1e5b 100644 --- a/readme.md +++ b/readme.md @@ -21,7 +21,7 @@ To integrate GradientLoadingBar into your Xcode project using [Carthage](https:/ ``` github "fxm90/GradientLoadingBar" ~> 1.0 ``` -Run carthage update to build the framework and drag the built `GradientLoadingBar.framework` (as well as the dependency [`Observable.framework`](https://github.com/roberthein/Observable)) into your Xcode project. +Run carthage update to build the framework and drag the built `GradientLoadingBar.framework` into your Xcode project. ### How to use To get started you'll have to import `GradientLoadingBar` into your file. To show the loading bar, simply call the `show()` method and after you're done with your operations call `hide()`.