From 1890d1aaf3d3ee741ab3b4f15062674815daa754 Mon Sep 17 00:00:00 2001 From: Hadi Dbouk Date: Fri, 10 Nov 2023 14:53:56 +0200 Subject: [PATCH] chore(targets): use one combine target and remove Podfile & UIKIt files --- FueledUtils.podspec | 82 --- .../CombineUIKit/ControlProtocol+Tapped.swift | 77 -- FueledUtils/CombineUIKit/TapAction.swift | 76 -- .../UIControl+ControlEventsPublisher.swift | 98 --- .../CombineUIKit/UITextInput+Combine.swift | 49 -- FueledUtils/FueledUtils.h | 23 - FueledUtils/Info.plist | 28 - .../UIKit/ButtonWithTitleAdjustment.swift | 111 --- FueledUtils/UIKit/ControlProtocol.swift | 34 - .../UIKit/DecoratingTextFieldDelegate.swift | 199 ------ FueledUtils/UIKit/DimmingButton.swift | 62 -- FueledUtils/UIKit/GradientView.swift | 278 -------- FueledUtils/UIKit/HairlineView.swift | 46 -- FueledUtils/UIKit/KeyboardInsetHelper.swift | 108 --- .../UIKit/LabelWithTitleAdjustment.swift | 115 --- FueledUtils/UIKit/ScrollViewPage.swift | 87 --- FueledUtils/UIKit/SetRootViewController.swift | 55 -- FueledUtils/UIKit/UIExtensions.swift | 667 ------------------ Package.swift | 66 +- .../FueledUtils}/Combine/Action.swift | 6 - .../FueledUtils}/Combine/ActionError.swift | 0 .../Combine}/ActionErrorProtocol.swift | 0 .../FueledUtils}/Combine/ActionProtocol.swift | 0 .../FueledUtils}/Combine/AnyAction.swift | 0 .../Combine/AnyCurrentValuePublisher.swift | 0 .../Combine/CoalescingAction.swift | 6 - .../CombineExtensions+Cancellables.swift | 6 - .../Combine/CombineExtensions.swift | 0 .../CombineOperators/Combine+Operators.swift | 12 +- .../CombineOperators+Optional.swift | 0 .../Combine/NSObject+CombineExtensions.swift | 0 .../Combine/ObservableObjectExtensions.swift | 6 - .../Combine/OverridingAction.swift | 0 .../Combine/Published+PublisherInit.swift | 0 .../Publisher+AdditionalHandleEvents.swift | 0 .../Combine/Publisher+CombinePrevious.swift | 0 .../Combine/Publisher+IgnoreRepeats.swift | 0 .../Combine/Publisher+TransferState.swift | 6 - .../Combine/PublisherExtensions.swift | 6 - .../Combine/PublishersExtensions.swift | 6 - .../Combine/Subject+SendResult.swift | 0 .../Subscriber+EraseToAnySubscriber.swift | 0 .../FueledUtils}/Core/AnyIdentifiable.swift | 0 .../FueledUtils}/Core/Atomic.swift | 0 .../Core/CollectionExtensions.swift | 0 .../FueledUtils}/Core/Lock.swift | 0 .../Core/NSDecimalNumberOperators.swift | 0 .../FueledUtils}/Core/OptionalProtocol.swift | 0 .../FueledUtils}/Core/OrderedSet.swift | 0 .../FueledUtils}/Core/Regex.swift | 0 .../Core/SequenceExtensions.swift | 0 .../FueledUtils}/Core/StringExtensions.swift | 0 .../FueledUtils}/Core/SwiftExtensions.swift | 0 .../FueledUtils}/Core/TransferState.swift | 0 .../FueledUtils}/SwiftUI/BackgroundBlur.swift | 0 .../SwiftUI/Binding+KeyPath.swift | 0 .../FueledUtils}/SwiftUI/BlurView.swift | 0 .../SwiftUI/EdgeInsets+Helpers.swift | 0 .../SwiftUI/ForEachWithIndex.swift | 0 .../SwiftUI/FramePreferenceKey.swift | 0 .../FueledUtils}/SwiftUI/View+AnyView.swift | 0 Tests/FueledUtils.xcodeproj/project.pbxproj | 433 ------------ .../contents.xcworkspacedata | 7 - .../FueledUtils/ReactiveSwift.xcscheme | 111 --- .../xcschemes/FueledUtilsTests.xcscheme | 63 -- .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../AnyCurrentValuePublisherSpec.swift | 10 +- .../CombineTests}/CoalescingActionSpec.swift | 10 +- .../CombineTests}/CombineLatestManySpec.swift | 10 +- .../CombineTests}/OverridingActionSpec.swift | 9 +- .../CombineTests}/SinkForLifetimeSpec.swift | 14 +- .../CoreTests}/OrderedSetSpec.swift | 7 +- Tests/Podfile | 14 - Tests/Podfile.lock | 43 -- Tests/Supporting Files/Info.plist | 22 - _Pods.xcodeproj | 1 - 77 files changed, 32 insertions(+), 3055 deletions(-) delete mode 100644 FueledUtils.podspec delete mode 100644 FueledUtils/CombineUIKit/ControlProtocol+Tapped.swift delete mode 100644 FueledUtils/CombineUIKit/TapAction.swift delete mode 100644 FueledUtils/CombineUIKit/UIControl+ControlEventsPublisher.swift delete mode 100644 FueledUtils/CombineUIKit/UITextInput+Combine.swift delete mode 100644 FueledUtils/FueledUtils.h delete mode 100644 FueledUtils/Info.plist delete mode 100644 FueledUtils/UIKit/ButtonWithTitleAdjustment.swift delete mode 100644 FueledUtils/UIKit/ControlProtocol.swift delete mode 100644 FueledUtils/UIKit/DecoratingTextFieldDelegate.swift delete mode 100644 FueledUtils/UIKit/DimmingButton.swift delete mode 100644 FueledUtils/UIKit/GradientView.swift delete mode 100644 FueledUtils/UIKit/HairlineView.swift delete mode 100644 FueledUtils/UIKit/KeyboardInsetHelper.swift delete mode 100644 FueledUtils/UIKit/LabelWithTitleAdjustment.swift delete mode 100644 FueledUtils/UIKit/ScrollViewPage.swift delete mode 100644 FueledUtils/UIKit/SetRootViewController.swift delete mode 100644 FueledUtils/UIKit/UIExtensions.swift rename {FueledUtils => Sources/FueledUtils}/Combine/Action.swift (98%) rename {FueledUtils => Sources/FueledUtils}/Combine/ActionError.swift (100%) rename {FueledUtils/ReactiveCommon => Sources/FueledUtils/Combine}/ActionErrorProtocol.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/ActionProtocol.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/AnyAction.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/AnyCurrentValuePublisher.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/CoalescingAction.swift (98%) rename {FueledUtils => Sources/FueledUtils}/Combine/CombineExtensions+Cancellables.swift (93%) rename {FueledUtils => Sources/FueledUtils}/Combine/CombineExtensions.swift (100%) rename {FueledUtils => Sources/FueledUtils/Combine}/CombineOperators/Combine+Operators.swift (96%) rename {FueledUtils => Sources/FueledUtils/Combine}/CombineOperators/CombineOperators+Optional.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/NSObject+CombineExtensions.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/ObservableObjectExtensions.swift (96%) rename {FueledUtils => Sources/FueledUtils}/Combine/OverridingAction.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/Published+PublisherInit.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/Publisher+AdditionalHandleEvents.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/Publisher+CombinePrevious.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/Publisher+IgnoreRepeats.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/Publisher+TransferState.swift (91%) rename {FueledUtils => Sources/FueledUtils}/Combine/PublisherExtensions.swift (97%) rename {FueledUtils => Sources/FueledUtils}/Combine/PublishersExtensions.swift (98%) rename {FueledUtils => Sources/FueledUtils}/Combine/Subject+SendResult.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Combine/Subscriber+EraseToAnySubscriber.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/AnyIdentifiable.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/Atomic.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/CollectionExtensions.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/Lock.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/NSDecimalNumberOperators.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/OptionalProtocol.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/OrderedSet.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/Regex.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/SequenceExtensions.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/StringExtensions.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/SwiftExtensions.swift (100%) rename {FueledUtils => Sources/FueledUtils}/Core/TransferState.swift (100%) rename {FueledUtils => Sources/FueledUtils}/SwiftUI/BackgroundBlur.swift (100%) rename {FueledUtils => Sources/FueledUtils}/SwiftUI/Binding+KeyPath.swift (100%) rename {FueledUtils => Sources/FueledUtils}/SwiftUI/BlurView.swift (100%) rename {FueledUtils => Sources/FueledUtils}/SwiftUI/EdgeInsets+Helpers.swift (100%) rename {FueledUtils => Sources/FueledUtils}/SwiftUI/ForEachWithIndex.swift (100%) rename {FueledUtils => Sources/FueledUtils}/SwiftUI/FramePreferenceKey.swift (100%) rename {FueledUtils => Sources/FueledUtils}/SwiftUI/View+AnyView.swift (100%) delete mode 100644 Tests/FueledUtils.xcodeproj/project.pbxproj delete mode 100644 Tests/FueledUtils.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Tests/FueledUtils.xcodeproj/xcshareddata/xcschemes/FueledUtils/ReactiveSwift.xcscheme delete mode 100644 Tests/FueledUtils.xcodeproj/xcshareddata/xcschemes/FueledUtilsTests.xcscheme delete mode 100644 Tests/FueledUtils.xcworkspace/contents.xcworkspacedata delete mode 100644 Tests/FueledUtils.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename Tests/{Tests => FueledUtils/CombineTests}/AnyCurrentValuePublisherSpec.swift (87%) rename Tests/{Tests => FueledUtils/CombineTests}/CoalescingActionSpec.swift (91%) rename Tests/{Tests => FueledUtils/CombineTests}/CombineLatestManySpec.swift (97%) rename Tests/{Tests => FueledUtils/CombineTests}/OverridingActionSpec.swift (92%) rename Tests/{Tests => FueledUtils/CombineTests}/SinkForLifetimeSpec.swift (90%) rename Tests/{Tests => FueledUtils/CoreTests}/OrderedSetSpec.swift (94%) delete mode 100644 Tests/Podfile delete mode 100644 Tests/Podfile.lock delete mode 100644 Tests/Supporting Files/Info.plist delete mode 120000 _Pods.xcodeproj diff --git a/FueledUtils.podspec b/FueledUtils.podspec deleted file mode 100644 index 93e43e69..00000000 --- a/FueledUtils.podspec +++ /dev/null @@ -1,82 +0,0 @@ -# frozen_string_literal: true - -Pod::Spec.new do |s| - s.name = 'FueledUtils' - s.version = '4.0.0' - s.summary = 'A collection of utilities used at Fueled' - s.description = 'This is a collection of classes, extensions, methods and functions used within Fueled projects that aims at decomplexifying tasks that should be easy.' - s.swift_version = '5' - - s.homepage = 'https://github.com/Fueled/ios-utilities' - s.license = { type: 'Apache License, Version 2.0', file: 'LICENSE' } - s.author = { 'Vadim-Yelagin' => 'vadim.yelagin@gmail.com', 'stephanecopin' => 'stephane@fueled.com', 'leontiy' => 'leonty@fueled.com', 'bastienFalcou' => 'bastien@fueled.com', 'heymansmile' => 'ivan@fueled.com', 'thib4ult' => 'thibault@fueled.com', 'notbenoit' => 'benoit@fueled.com' } - s.source = { git: 'https://github.com/Fueled/ios-utilities.git', tag: s.version.to_s } - s.documentation_url = 'https://cdn.rawgit.com/Fueled/ios-utilities/master/docs/index.html' - - s.ios.deployment_target = '9.0' - s.osx.deployment_target = '10.12' - s.watchos.deployment_target = '2.0' - s.tvos.deployment_target = '9.0' - - s.subspec 'Core' do |s| - s.source_files = 'FueledUtils/Core/**/*.swift' - end - - s.subspec 'ReactiveCommon' do |s| - s.source_files = 'FueledUtils/ReactiveCommon/**/*.swift' - - s.dependency 'FueledUtils/Core' - end - - s.subspec 'UIKit' do |s| - s.dependency 'FueledUtils/Core' - s.ios.source_files = 'FueledUtils/UIKit/**/*.swift' - end - - s.subspec 'Combine' do |s| - # Update the above with the following versions when we drop support for iOS < 13.0 or - # uncomment below if https://github.com/CocoaPods/CocoaPods/issues/7333 is implemented - # s.ios.deployment_target = '13.0' - # s.osx.deployment_target = '10.15' - # s.watchos.deployment_target = '6.0' - # s.tvos.deployment_target = '13.0' - - s.dependency 'FueledUtils/ReactiveCommon' - - s.source_files = 'FueledUtils/Combine/**/*.swift' - end - - s.subspec 'CombineOperators' do |s| - s.dependency 'FueledUtils/Combine' - - s.source_files = 'FueledUtils/CombineOperators/**/*.swift' - end - - s.subspec 'CombineUIKit' do |s| - s.dependency 'FueledUtils/Combine' - s.dependency 'FueledUtils/UIKit' - - s.ios.source_files = 'FueledUtils/CombineUIKit/**/*.swift' - end - - s.subspec 'SwiftUI' do |s| - s.dependency 'FueledUtils/Core' - s.dependency 'FueledUtils/Combine' - - s.source_files = 'FueledUtils/SwiftUI/**/*.swift' - end - - s.subspec 'ReactiveCombineBridge' do |s| - s.dependency 'FueledUtils/ReactiveSwift' - s.dependency 'FueledUtils/Combine' - - s.source_files = 'FueledUtils/ReactiveCombineBridge/**/*.swift' - end - - s.osx.exclude_files = ['FueledUtils/FueledUtils.h', 'FueledUtils/ButtonWithTitleAdjustment.swift', 'FueledUtils/DecoratingTextFieldDelegate.swift', 'FueledUtils/DimmingButton.swift', 'FueledUtils/HairlineView.swift', 'FueledUtils/HairlineView.swift', 'FueledUtils/KeyboardInsetHelper.swift', 'FueledUtils/LabelWithTitleAdjustment.swift', 'FueledUtils/ReactiveCocoaExtensions.swift', 'FueledUtils/ScrollViewPage.swift', 'FueledUtils/SetRootViewController.swift', 'FueledUtils/SignalingAlert.swift', 'FueledUtils/UIExtensions.swift', 'FueledUtils/GradientView.swift'] - s.ios.exclude_files = ['FueledUtils/FueledUtils.h'] - s.watchos.exclude_files = ['FueledUtils/FueledUtils.h', 'FueledUtils/ButtonWithTitleAdjustment.swift', 'FueledUtils/DecoratingTextFieldDelegate.swift', 'FueledUtils/DimmingButton.swift', 'FueledUtils/HairlineView.swift', 'FueledUtils/HairlineView.swift', 'FueledUtils/KeyboardInsetHelper.swift', 'FueledUtils/LabelWithTitleAdjustment.swift', 'FueledUtils/ReactiveCocoaExtensions.swift', 'FueledUtils/ScrollViewPage.swift', 'FueledUtils/SetRootViewController.swift', 'FueledUtils/SignalingAlert.swift', 'FueledUtils/UIExtensions.swift', 'FueledUtils/GradientView.swift'] - s.tvos.exclude_files = ['FueledUtils/FueledUtils.h', 'FueledUtils/KeyboardInsetHelper.swift'] - - s.default_subspecs = 'Core' -end diff --git a/FueledUtils/CombineUIKit/ControlProtocol+Tapped.swift b/FueledUtils/CombineUIKit/ControlProtocol+Tapped.swift deleted file mode 100644 index 6869bd7a..00000000 --- a/FueledUtils/CombineUIKit/ControlProtocol+Tapped.swift +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) && canImport(Combine) -import Combine -#if canImport(FueledUtilsUIKit) -import Foundation -import FueledUtilsUIKit -#endif - -private var tapActionStorage: UInt8 = 0 -private var tapActionKey: UInt8 = 0 - -@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) -extension ControlProtocol { - /// - /// The action to be triggered when the button is tapped. - /// This mirrors the `pressed` property native in `ReactiveCocoa`, but uses a - /// protocol to represents the button rather than hardcode it to classes, - /// allowing for any `UIControl` to use this method. - /// - public var tapped: TapAction? { - get { - self.tapActionStorage?.tapAction - } - set { - self.tapActionStorage = nil - - if let newValue = newValue { - let tapActionStorage = TapActionStorage(newValue) - newValue.$isEnabled.assign(to: \.isEnabled, withoutRetaining: self) - .store(in: &tapActionStorage.cancellables) - if let self = self as? ControlLoadingProtocol { - newValue.$isExecuting.sink { [weak self] in - self?.isLoading = $0 - } - .store(in: &tapActionStorage.cancellables) - } - self.removeTarget(newValue, action: TapAction.selector, for: .primaryActionTriggered) - self.addTarget(newValue, action: TapAction.selector, for: .primaryActionTriggered) - self.tapActionStorage = tapActionStorage - } - } - } - - private var tapActionStorage: TapActionStorage? { - get { - objc_getAssociatedObject(self, &tapActionKey) as? TapActionStorage - } - set { - objc_setAssociatedObject(self, &tapActionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) - } - } -} - -@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) -private final class TapActionStorage { - let tapAction: TapAction - var cancellables = Set() - - init(_ tapAction: TapAction) { - self.tapAction = tapAction - } -} - -#endif diff --git a/FueledUtils/CombineUIKit/TapAction.swift b/FueledUtils/CombineUIKit/TapAction.swift deleted file mode 100644 index cd65ef1d..00000000 --- a/FueledUtils/CombineUIKit/TapAction.swift +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import Foundation -import UIKit -#if canImport(Combine) -import Combine -#endif -#if canImport(FueledUtilsCombine) -import FueledUtilsCombine -#endif - -/// -/// `TapAction` wraps a `ActionProtocol` for use by any `ControlProtocol`. -@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) -public final class TapAction: NSObject { - @objc static var selector: Selector { - #selector(userDidTapControl(_:)) - } - - @Published private(set) var isExecuting: Bool = false - @Published private(set) var isEnabled: Bool = false - - // FIXME: (Stéphane) To be retested for the next version of Swift (after 5.3) - // Any initializers below create a segfault when compiling with optimizations. - private let inputTransform: ((Control) -> Any) - private let confirmAction: ((@escaping () -> Void) -> Void)? - private let action: AnyAction - private var cancellables = Set() - - public convenience init(_ action: Action, confirmAction: ((@escaping () -> Void) -> Void)? = nil) where Action.Input == Void { - self.init(action, input: (), confirmAction: confirmAction) - } - - public convenience init(_ action: Action, input: Action.Input, confirmAction: ((@escaping () -> Void) -> Void)? = nil) { - self.init(action, confirmAction: confirmAction, inputTransform: { _ in input }) - } - - public init(_ action: Action, confirmAction: (((@escaping () -> Void) -> Void))? = nil, inputTransform: @escaping (Control) -> Action.Input) { - self.isEnabled = action.isEnabled - self.isExecuting = action.isExecuting - self.inputTransform = { inputTransform($0) } - self.confirmAction = confirmAction - self.action = AnyAction(action) - super.init() - self.action.isEnabledPublisher.assign(to: \.isEnabled, withoutRetaining: self) - .store(in: &self.cancellables) - self.action.isExecutingPublisher.assign(to: \.isExecuting, withoutRetaining: self) - .store(in: &self.cancellables) - } - - @objc private func userDidTapControl(_ button: Any) { - let confirmAction = self.confirmAction ?? { $0() } - confirmAction { [weak self] in - guard let self = self else { - return - } - - self.action.apply(self.inputTransform(button as! Control)).sink() - .store(in: &self.cancellables) - } - } -} -#endif diff --git a/FueledUtils/CombineUIKit/UIControl+ControlEventsPublisher.swift b/FueledUtils/CombineUIKit/UIControl+ControlEventsPublisher.swift deleted file mode 100644 index 4de3f5a0..00000000 --- a/FueledUtils/CombineUIKit/UIControl+ControlEventsPublisher.swift +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) && canImport(Combine) -import Combine -import UIKit -#if canImport(FueledUtilsUIKit) -import Foundation -import FueledUtilsUIKit -#endif - -private var publisherControlEventsProcessorsHolderKey: UInt8 = 0 - -@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) -extension ControlProtocol { - public func publisherForControlEvents(_ controlEvents: UIControl.Event) -> AnyPublisher { - let passthroughSubject = PassthroughSubject() - var cancellable: AnyCancellable! = self.publisherControlEventsProcessorsHolder.addProcessor( - for: controlEvents, - in: self, - passthroughSubject: passthroughSubject - ) - _ = cancellable - return passthroughSubject - .map { - $0 as! Self - } - .handleEvents( - receiveCancel: { - cancellable = nil - } - ) - .eraseToAnyPublisher() - } - - private var publisherControlEventsProcessorsHolder: PublisherControlEventsProcessorsHolder { - get { - objc_getAssociatedObject(self, &publisherControlEventsProcessorsHolderKey) as? PublisherControlEventsProcessorsHolder ?? { - let publisherControlEventsProcessorsHolder = PublisherControlEventsProcessorsHolder() - self.publisherControlEventsProcessorsHolder = publisherControlEventsProcessorsHolder - return publisherControlEventsProcessorsHolder - }() - } - set { - objc_setAssociatedObject(self, &publisherControlEventsProcessorsHolderKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) - } - } -} - -@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) -private final class PublisherControlEventsProcessorsHolder { - private final class PublisherControlEventsProcessor: NSObject { - weak var passthroughSubject: PassthroughSubject! - - init(control: ControlProtocol, controlEvents: UIControl.Event, passthroughSubject: PassthroughSubject) { - self.passthroughSubject = passthroughSubject - super.init() - control.addTarget(self, action: #selector(PublisherControlEventsProcessor.handleControlEvents(_:)), for: controlEvents) - } - - @objc func handleControlEvents(_ sender: Any) { - self.passthroughSubject.send(sender) - } - } - - private var processors: [PublisherControlEventsProcessor] = [] - - init() { - } - - func addProcessor( - for controlEvents: UIControl.Event, - in control: ControlProtocol, - passthroughSubject: PassthroughSubject - ) -> AnyCancellable { - let processor = PublisherControlEventsProcessor( - control: control, - controlEvents: controlEvents, - passthroughSubject: passthroughSubject - ) - return AnyCancellable { - self.processors.removeAll { $0 === processor } - } - } -} - -#endif diff --git a/FueledUtils/CombineUIKit/UITextInput+Combine.swift b/FueledUtils/CombineUIKit/UITextInput+Combine.swift deleted file mode 100644 index 20296309..00000000 --- a/FueledUtils/CombineUIKit/UITextInput+Combine.swift +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2020 Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) && canImport(Combine) -import Combine -#if canImport(FueledUtilsCombine) -import FueledUtilsCombine -#endif -#if canImport(FueledUtilsUIKit) -import FueledUtilsUIKit -#endif -import UIKit - -@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) -extension CombineExtensions where Base: UITextInput, Base: ControlProtocol { - public var textValues: AnyPublisher { - self.textPublisherForControlEvents([.editingDidEnd, .editingDidEndOnExit]) - } - - public var continuousTextValues: AnyPublisher { - self.textPublisherForControlEvents(.allEditingEvents) - } - - private func textPublisherForControlEvents(_ controlEvents: UIControl.Event) -> AnyPublisher { - self.base.publisherForControlEvents(controlEvents) - .map { textInput in - textInput.textRange( - from: textInput.beginningOfDocument, - to: textInput.endOfDocument - ) - .flatMap { textInput.text(in: $0) } - ?? "" - } - .eraseToAnyPublisher() - } -} - -#endif diff --git a/FueledUtils/FueledUtils.h b/FueledUtils/FueledUtils.h deleted file mode 100644 index 56eb2098..00000000 --- a/FueledUtils/FueledUtils.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - Copyright © 2019 Fueled Digital Media, LLC - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#import - -//! Project version number for FueledUtils. -FOUNDATION_EXPORT double FueledUtilsVersionNumber; - -//! Project version string for FueledUtils. -FOUNDATION_EXPORT const unsigned char FueledUtilsVersionString[]; diff --git a/FueledUtils/Info.plist b/FueledUtils/Info.plist deleted file mode 100644 index b36a87ea..00000000 --- a/FueledUtils/Info.plist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSHumanReadableCopyright - Copyright © 2019 Fueled. All rights reserved. - NSPrincipalClass - - - diff --git a/FueledUtils/UIKit/ButtonWithTitleAdjustment.swift b/FueledUtils/UIKit/ButtonWithTitleAdjustment.swift deleted file mode 100644 index d3f39194..00000000 --- a/FueledUtils/UIKit/ButtonWithTitleAdjustment.swift +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#if canImport(UIKit) && !os(watchOS) -import UIKit - -/// -/// A subclass of `UIButton` allowing to easily specify line spacing and kerning. -/// -/// This class exposes properties allowing to customize the title in Interface Builder. -/// Internally, this class works by setting `setAttributedTitle(_:, for:)`. **Do not use** -/// this class if you're using `setAttributedTitle(_:, for:)` anywhere. -/// -open class ButtonWithTitleAdjustment: UIButton { - /// - /// The line spacing to apply to the button's title. - /// - /// Negative values are **unsupported**. Please refer to the documentation for `NSAttributedString.Key.lineSpacing` for more info. - /// - @IBInspectable public var adjustmentLineSpacing: CGFloat = 0.0 { - didSet { - self.updateAdjustedTitles() - } - } - - /// - /// The kern value to apply to the button's title. - /// - /// Please refer to the documentation for `NSAttributedString.Key.kernValue` for info about the possible values. - /// - @IBInspectable public var adjustmentKerning: CGFloat = 0.0 { - didSet { - self.updateAdjustedTitles() - } - } - - /// - /// Please refer to the documentation for `UIButton.init(frame:)` - /// - override public init(frame: CGRect) { - super.init(frame: frame) - self.updateAdjustedTitles() - } - - /// - /// Please refer to the documentation for `UIButton.init(coder:)` - /// - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - self.updateAdjustedTitles() - } - - /// - /// Please refer to the documentation for `UIButton.setTitleColor(_:, for:)` - /// - override open func setTitleColor(_ color: UIColor?, for state: UIControl.State) { - super.setTitleColor(color, for: state) - self.updateAdjustedTitles() - } - - /// - /// Please refer to the documentation for `UIButton.setTitle(_:, for:)` - /// - override open func setTitle(_ title: String?, for state: UIControl.State) { - super.setTitle(title, for: state) - self.updateAdjustedTitles() - } - - private func updateAdjustedTitles() { - let states: [UIControl.State] - if #available(iOS 9.0, *) { - states = [.normal, .focused, .highlighted, .selected, .disabled, [.selected, .highlighted], [.selected, .disabled]] - } else { - states = [.normal, .highlighted, .selected, .disabled, [.selected, .highlighted], [.selected, .disabled]] - } - for state in states { - self.setAdjustedTitle(self.title(for: state), for: state) - } - } - - private func setAdjustedTitle(_ title: String?, for state: UIControl.State) { - let adjustedString = title.map { title -> NSAttributedString in - let paragraphStyle = NSMutableParagraphStyle() - paragraphStyle.lineSpacing = self.adjustmentLineSpacing - if let titleLabel = self.titleLabel { - paragraphStyle.lineBreakMode = titleLabel.lineBreakMode - paragraphStyle.alignment = titleLabel.textAlignment - } - var attributes: [NSAttributedString.Key: Any] = [ - .paragraphStyle: paragraphStyle, - .kern: self.adjustmentKerning, - ] - if let titleColor = self.titleColor(for: state) { - attributes[.foregroundColor] = titleColor - } - return NSAttributedString(string: title, attributes: attributes) - } - self.setAttributedTitle(adjustedString, for: state) - } -} -#endif diff --git a/FueledUtils/UIKit/ControlProtocol.swift b/FueledUtils/UIKit/ControlProtocol.swift deleted file mode 100644 index e9f869ef..00000000 --- a/FueledUtils/UIKit/ControlProtocol.swift +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import UIKit - -/// -/// A protocol that represents a control, which must be a `UIControl`. -/// -public protocol ControlProtocol: UIControl { -} - -/// -/// A protocol that represents a control with a `isLoading` property. -/// -public protocol ControlLoadingProtocol: ControlProtocol { - var isLoading: Bool { get set } -} - -// Make all `UIControl` a `ControlProtocol` by default. -extension UIControl: ControlProtocol { -} -#endif diff --git a/FueledUtils/UIKit/DecoratingTextFieldDelegate.swift b/FueledUtils/UIKit/DecoratingTextFieldDelegate.swift deleted file mode 100644 index 62e37809..00000000 --- a/FueledUtils/UIKit/DecoratingTextFieldDelegate.swift +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import UIKit -import Foundation -#if canImport(FueledUtilsCore) -import FueledUtilsCore -#endif - -/// -/// Adds formatting (decoration) characters to text field's content according to a variable pattern. Can be used for -/// payment card number formatting, phone number formatting, etc. -/// -public final class DecoratingTextFieldDelegate: NSObject { - /// - /// `DecoratingTextFieldDelegate` will call this function passing current data string as a - /// parameter every time the data string changes, the returned pattern will subsequently be used to format the data - /// string passed. - /// - public let patternForDataString: (String) -> String - /// - /// A character that is not a formatting character. - /// - public let patternPlaceholderForDataCharacter: Character - /// - /// A predicate to filter non-data characters from user's input. No matter what user tries to put - /// into the textfield, only characters for which `isDataCharacter` returns `true` will appear in the text field. - /// - public let isDataCharacter: (Character) -> Bool - - /// - /// Initializes a delegate with a fixed pattern - /// - Parameters: - /// - pattern: A string containing data placeholder and formatting characters. - /// - patternPlaceholderForDataCharacter: A character that is not a formatting character. - /// - isDataCharacter: A predicate to filter non-data characters from user's input. No matter what user tries to put - /// into the textfield, only characters for which `isDataCharacter` returns `true` will appear in the text field. - /// - /// ## Example: - /// A 16-digit VISA payment card pattern might look like this `####-####-####-####` `'#'` is a - /// `patternPlaceholderForDataCharacter` and '`-`' is a formatting (decorating) character. - /// - public convenience init( - pattern: String, - patternPlaceholderForDataCharacter: Character, - isDataCharacter: @escaping (Character) -> Bool) - { - self.init( - patternForDataString: { _ in pattern }, - patternPlaceholderForDataCharacter: patternPlaceholderForDataCharacter, - isDataCharacter: isDataCharacter - ) - } - - /// - /// Intializes a delegate with a fixed pattern - /// - /// - Parameters: - /// - patternForDataString: `DecoratingTextFieldDelegate` will call this function passing current data string as a - /// parameter every time the data string changes, the returned pattern will subsequently be used to format the data - /// string passed. - /// - patternPlaceholderForDataCharacter: A character that is not a formatting character. - /// - isDataCharacter: A predicate to filter non-data characters from user's input. No matter what user tries to put - /// into the textfield, only characters for which `isDataCharacter` returns `true` will appear in the text field. - /// - /// ## Example: - /// A 16-digit VISA payment card pattern might look like this `####-####-####-####` `'#'` is a - /// `patternPlaceholderForDataCharacter` and '`-`' is a formatting (decorating) character. Furthermore, to support - /// various kinds of payment cards a more complex behaviour may need to be implemented where the first 6 digits of a - /// payment card number will define total length and formatting pattern for any valid card number starting with those 6 - /// digits. This behaviour can be implemented by using `patternForDataString`. - /// - public init( - patternForDataString: @escaping (String) -> String, - patternPlaceholderForDataCharacter: Character, - isDataCharacter: @escaping (Character) -> Bool) - { - self.patternForDataString = patternForDataString - self.patternPlaceholderForDataCharacter = patternPlaceholderForDataCharacter - self.isDataCharacter = isDataCharacter - super.init() - } - - /// - /// Decorate a string consisting of data characters (see `isDataCharacter`) into a string converted using `patternForDataString` - /// - /// - Parameters: - /// - dataString: A string containing only data characters (see `isDataCharacter`). - /// - /// - Returns: The converted string from the input. - /// - public func decorateString(_ dataString: String) -> String { - var result = "" - var dataIndex = dataString.startIndex - let pattern = self.patternForDataString(dataString) - for patternChar in pattern { - if patternChar == self.patternPlaceholderForDataCharacter { - if dataIndex == dataString.endIndex { - return result - } - result += String(dataString[dataIndex]) - dataIndex = dataString.index(after: dataIndex) - } else { - result += String(patternChar) - } - } - return result - } - - /// - /// Strips formatting (decoration) characters from the input string, checking each character using `isDataCharacter` - /// and removing it from the input. - /// - /// - Parameters: - /// - dataString: A string contained any kind of characters - /// - /// - Returns: The undecorated string from the input. - /// - public func undecorateString(_ decoratedString: String) -> String { - var result = "" - for decoratedChar in decoratedString { - if self.isDataCharacter(decoratedChar) { - result += String(decoratedChar) - } - } - return result - } - - fileprivate func convertDecoratedRange(_ decoratedRange: NSRange, fromDecoratedString decoratedString: String) -> NSRange { - let decoratedPrefix = (decoratedString as NSString).substring(to: decoratedRange.location) - let decoratedSubstring = (decoratedString as NSString).substring(with: decoratedRange) - let dataPrefix = self.undecorateString(decoratedPrefix) - let dataSubstring = self.undecorateString(decoratedSubstring) - return NSRange(location: dataPrefix.nsLength, length: dataSubstring.nsLength) - } - - fileprivate func convertDataLocation(_ dataLocation: Int, toDecoratedString decoratedString: String) -> Int { - if dataLocation <= 0 { - return dataLocation - } - var res = 0 - var prefixLength = dataLocation - for decoChar in decoratedString { - let characterLength = String(decoChar).nsLength - if self.isDataCharacter(decoChar) { - if prefixLength <= 0 { - return res - } - prefixLength -= characterLength - } - res += characterLength - } - return decoratedString.nsLength - } -} - -extension DecoratingTextFieldDelegate: UITextFieldDelegate { - /// - /// Please refer to the documentation for `UITextFieldDelegate.textField(_:, shouldChangeCharactersIn:, replacementString:)`. - /// - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - let decoratedString = textField.text ?? "" - let decoratedReplacement = string - let dataString = undecorateString(decoratedString) - let dataReplacement = self.undecorateString(decoratedReplacement) - var dataRange = self.convertDecoratedRange(range, fromDecoratedString: decoratedString) - if range.length > 0 && decoratedReplacement.isEmpty && dataRange.length == 0 && dataRange.location > 0 { - // probably backspace was hit with no data characters selected or prior to cursor - // in this case we grow data range by one prior data character (if possible) - // in order to erase that data character - dataRange = (dataString as NSString).rangeOfComposedCharacterSequence(at: dataRange.location - 1) - } - - let newDataString = (dataString as NSString).replacingCharacters(in: dataRange, with: dataReplacement) - let newDecoratedString = decorateString(newDataString) - textField.text = newDecoratedString - textField.sendActions(for: .editingChanged) - - let newDataLocation = dataRange.location + dataReplacement.nsLength - let newDecoratedLocation = convertDataLocation(newDataLocation, toDecoratedString: newDecoratedString) - if let selectedPos = textField.position(from: textField.beginningOfDocument, offset: newDecoratedLocation) { - textField.selectedTextRange = textField.textRange(from: selectedPos, to: selectedPos) - } - return false - } -} -#endif diff --git a/FueledUtils/UIKit/DimmingButton.swift b/FueledUtils/UIKit/DimmingButton.swift deleted file mode 100644 index f0d862be..00000000 --- a/FueledUtils/UIKit/DimmingButton.swift +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import Foundation -import UIKit - -/// -/// A button that dims a view when highlighted. -/// -public final class DimmingButton: UIButton { - /// - /// The view to dim while highlighted - /// - /// - Note: If `dimmingView` is `nil`, the button itself is dimmed. - /// - @IBOutlet public weak var dimmingView: UIView? { - willSet { - self.updateDimmedAmount(for: self.dimmingView, dimmedAlpha: 1.0) - } - didSet { - self.updateDimmedViewAmount() - } - } - /// - /// The alpha to set the view to when dimmed. Defaults to `0.4` - /// - @IBInspectable public var dimmedAlpha: CGFloat = 0.4 { - didSet { - self.updateDimmedViewAmount() - } - } - - /// - /// Please refer to the documentation for `UIButton.isHighlighted`. - /// - public override var isHighlighted: Bool { - didSet { - self.updateDimmedViewAmount() - } - } - - private func updateDimmedViewAmount() { - self.updateDimmedAmount(for: self.dimmingView, dimmedAlpha: self.isHighlighted ? self.dimmedAlpha : 1.0) - } - - private func updateDimmedAmount(for view: UIView?, dimmedAlpha: CGFloat) { - (view ?? self).alpha = dimmedAlpha - } -} -#endif diff --git a/FueledUtils/UIKit/GradientView.swift b/FueledUtils/UIKit/GradientView.swift deleted file mode 100644 index d059cc29..00000000 --- a/FueledUtils/UIKit/GradientView.swift +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import UIKit - -/// -/// An easy to use wrapper around `CGGradient` for drawing linear gradients. -/// -/// For examples and testing its usage, you can use the `FueledUtils` playground file provided with the workspace. -/// -public final class GradientView: UIView { - /// - /// Defines the colors of a given type. - /// - public enum Definition { - /// - /// Defines a simple gradient, that has a start color and an end color - /// - case simple(startColor: UIColor, endColor: UIColor) - /// - /// Defines a custom gradient, that has as many colors and location point as wanted. - /// It should at least contain 2 elements. - /// When used in `GradientView`, it ensures that it is the case, and will report a - /// crash at runtime if the array has less than 2 elements. - /// - case custom([(color: UIColor, location: CGFloat)]) - - /// - /// Get the start color of the receiver. - /// If the current value is `.simple`, returns `startColor`. - /// If the current value is `.custom`, returns the first color of the array. If the array is empty, this will crash at runtime. - /// - public var startColor: UIColor { - switch self { - case .simple(let startColor, _): - return startColor - case .custom(let colors): - return colors.first!.color - } - } - - /// - /// Get the end color of the receiver. - /// If the current value is `.simple`, returns `endColor`. - /// If the current value is `.custom`, returns the last color of the array. If the array is empty, this will crash at runtime. - /// - public var endColor: UIColor { - switch self { - case .simple(_, let endColor): - return endColor - case .custom(let colors): - return colors.last!.color - } - } - - fileprivate var gradientInfo: [(color: UIColor, location: CGFloat)] { - switch self { - case .simple(let startColor, let endColor): - return [ - (startColor, 0.0), - (endColor, 1.0), - ] - case .custom(let colors): - return colors - } - } - } - - /// - /// Defines the different type of supported gradients. - /// - public enum GradientType { - /// - /// Defines a linear gradient type, along the specified direction. - /// When used with `GradientView`, `direction` is scaled to the bounds of the view. - /// - /// ## Examples - /// - `.linear(direction: CGPoint(x: 0.0, y: 1.0)`: Define a gradient going from the left edge to the right edge. - /// - `.linear(direction: CGPoint(x: 1.0, y: 1.0)`: Define a gradient going from the top-left corner to the bottom-right corner. - /// - `.linear(direction: CGPoint(x: -1.0, y: -1.0)`: Define a gradient going from the bottom-right corner to the top-left corner. - /// - `.linear(direction: CGPoint(x: -1.0, y: 0.0)`: Define a gradient going from the bottom edge to the top edge. - /// - `.linear(direction: CGPoint(x: 0.0, y: 0.5)`: Define a gradient going from the top edge to the middle, extending the last color until the bottom edge. - /// - /// - Note: If `direction` is `.zero`, only the `endColor` of the `Definition` will be drawn. See `GradientView.Definition.endColor` for more info - /// about what this property refers to. - /// - case linear(direction: CGPoint) - /// - /// Defines a radial gradient type, starting at the specified center with the given initial radius, and expanding/reducing to the specified center and final radius. - /// When used with `GradientView`, `startCenter` and `endCenter` is scaled to the bounds of the view. `startRadius` and `endRadius` are not scaled. - /// - /// ## Examples - /// - `.radial(startCenter: CGPoint(x: 0.5, y: 0.5), startRadius: 10.0, endCenter: CGPoint(x: 0.5, y: 0.5), endRadius: 200.0)`: Define a radial gradient that starts - /// in the center of the view with an initial radius of 10, and expands to a radius of 200 without changing its center. - /// - `.radial(startCenter: CGPoint(x: 0.0, y: 0.5), startRadius: 200.0, endCenter: CGPoint(x: 1.0, y: 0.5), endRadius: 10.0)`: Define a radial gradient that starts - /// in the left edge of the view centered vertically with an initial radius of 200, and reduce to a radius of 50 to the right-most edge centered vertically. - /// - /// - Note: When using different centers for a radial gradient, the resulting gradient might be unexpected. - /// - case radial(startCenter: CGPoint, startRadius: CGFloat, endCenter: CGPoint, endRadius: CGFloat) - } - - /// - /// Get/Set the type of the gradient. Please refer to `GradientType` for more info. - /// - public var type: GradientType = .linear(direction: .verticalDirection) { - didSet { - self.setNeedsDisplay() - } - } - - /// - /// Get/Set the definition of the gradient. Please refer to `Definition` for more info. - /// - /// - Warning: If the definition is `.custom`, and the array has less than 2 elements, the code will crash at runtime. - /// - public var definition: Definition = .simple(startColor: .black, endColor: .white) { - didSet { - if case .custom(let info) = self.definition, info.count < 2 { - fatalError(".custom() must have at least 2 colors to make a gradient") - } - self.setNeedsDisplay() - } - } - - /// - /// Get/Set the start color of the gradient. - /// When getting the property, if the gradient is `.custom`, it will return the first color in the array. - /// When setting this property, if the gradient is `.custom`, it will convert it to a `.simple` using - /// the last color of the array as the `endColor`. - /// - @IBInspectable - public var startColor: UIColor { - get { - return self.definition.startColor - } - set { - self.definition = .simple(startColor: newValue, endColor: self.definition.endColor) - } - } - - /// - /// Get/Set the end color of the gradient. - /// When getting the property, if the gradient is `.custom`, it will return the last color in the array. - /// When setting this property, if the gradient is `.custom`, it will convert it to a `.simple` using - /// the first color of the array as the `startColor`. - /// - @IBInspectable - public var endColor: UIColor { - get { - return self.definition.endColor - } - set { - self.definition = .simple(startColor: self.definition.startColor, endColor: newValue) - } - } - - /// - /// Get/set the direction of the gradient. Returns `.zero` if the configured gradient is not `.linear` - /// When setting this property, if the gradient is not `.linear`, it is converted to a `.linear` gradient with the given direction. - /// - @IBInspectable var direction: CGPoint { - get { - if case .linear(let direction) = self.type { - return direction - } - return .zero - } - set { - self.type = .linear(direction: newValue) - } - } - - /// - /// Please refer to the documentation for `UIView.init(frame:)` - /// - override public init(frame: CGRect) { - super.init(frame: frame) - self.commonInit() - } - - /// - /// Please refer to the documentation for `UIView.init(coder:)` - /// - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - self.commonInit() - } - - private func commonInit() { - self.contentMode = .redraw - // https://stackoverflow.com/a/43898524/3605958 - // The background color must be set to a non-nil value or drawRect(_:) will not render the gradient properly - self.backgroundColor = UIColor.clear - } - - /// - /// Please refer to the documentation for `UIView.draw(_:)` - /// - override public func draw(_ rect: CGRect) { - let context = UIGraphicsGetCurrentContext()! - let colors = self.definition.gradientInfo.map { $0.color.cgColor } - var locations = self.definition.gradientInfo.map { $0.location } - let colorSpace = CGColorSpaceCreateDeviceRGB() - let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! - switch self.type { - case .linear(let direction): - let baseEnd = CGPoint( - x: self.bounds.size.width * direction.x, - y: self.bounds.size.height * direction.y - ) - context.drawLinearGradient( - gradient, - start: CGPoint( - x: baseEnd.x < 0.0 ? -baseEnd.x : 0.0, - y: baseEnd.y < 0.0 ? -baseEnd.y : 0.0 - ), - end: CGPoint( - x: baseEnd.x < 0.0 ? 0.0 : baseEnd.x, - y: baseEnd.y < 0.0 ? 0.0 : baseEnd.y - ), - options: [ - .drawsBeforeStartLocation, - .drawsAfterEndLocation, - ] - ) - case .radial(let startCenter, let startRadius, let endCenter, let endRadius): - let startCenter = CGPoint( - x: self.bounds.size.width * startCenter.x, - y: self.bounds.size.height * startCenter.y - ) - let endCenter = CGPoint( - x: self.bounds.size.width * endCenter.x, - y: self.bounds.size.height * endCenter.y - ) - context.drawRadialGradient( - gradient, - startCenter: startCenter, - startRadius: startRadius, - endCenter: endCenter, - endRadius: endRadius, - options: [ - .drawsBeforeStartLocation, - .drawsAfterEndLocation, - ] - ) - } - } -} - -extension CGPoint { - /// - /// Defines a vertical top to down direction. - /// - public static var verticalDirection: CGPoint { - return CGPoint(x: 0.0, y: 1.0) - } - - /// - /// Defines a horizontal left to right direction. - /// - public static var horizontalDirection: CGPoint { - return CGPoint(x: 1.0, y: 0.0) - } -} -#endif diff --git a/FueledUtils/UIKit/HairlineView.swift b/FueledUtils/UIKit/HairlineView.swift deleted file mode 100644 index fa135ba6..00000000 --- a/FueledUtils/UIKit/HairlineView.swift +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import Foundation -import UIKit - -/// -/// A view with an intrinsic content size of 1px by 1px -/// -open class HairlineView: UIView { - /// - /// Please refer to the documentation for `UIView.intrinsicContentSize` - /// - override open var intrinsicContentSize: CGSize { - let pixel = 1.0 / UIScreen.main.scale - return CGSize(width: pixel, height: pixel) - } - - /// - /// Please refer to the documentation for `UIView.backgroundColor` - /// - override open var backgroundColor: UIColor? { - set { - // prevent backgroundColor becoming clearColor on parent UITableViewCell selection - if newValue != UIColor.clear { - super.backgroundColor = newValue - } - } - get { - return super.backgroundColor - } - } -} -#endif diff --git a/FueledUtils/UIKit/KeyboardInsetHelper.swift b/FueledUtils/UIKit/KeyboardInsetHelper.swift deleted file mode 100644 index 7efe9d17..00000000 --- a/FueledUtils/UIKit/KeyboardInsetHelper.swift +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) && !os(tvOS) -import Foundation -import UIKit - -/// -/// Binds keyboard appearance and metrics to scroll view content and scroll bar insets and/or a layout constraint -/// relative to reference view. This object can be created and linked in a sotryboard. -/// -open class KeyboardInsetHelper: NSObject { - /// - /// The minimum inset value. Inset values below this value are clamped to `minimumInset`. - /// - @IBInspectable public var minimumInset: CGFloat = 0 - /// - /// The inset and constraint constant will be calculated in the coordinates of this view. - /// This variable must be non-`nil`, otherwise the insets won't get updated. - /// - @IBOutlet public weak var referenceView: UIView? - /// - /// Scroll view to adjust content inset at. When the keyboard appears or disappears, the inset will be adjusted to - /// align the bottom of the scroll view's content with the top of the keyboard (`minimumInset` takes priority). - /// - @IBOutlet public weak var scrollView: UIScrollView? - /// - /// When the keyboard appears or disappears, the constraint's constant will be set to the distance between the bottom of the - /// reference view and the top of the keyboard but no less than `minimumInset`. - /// - @IBOutlet public weak var constraint: NSLayoutConstraint? - - public override init() { - super.init() - NotificationCenter.default.addObserver( - self, - selector: #selector(handleKeyboardNotification(_:)), - name: UIResponder.keyboardWillShowNotification, - object: nil - ) - NotificationCenter.default.addObserver( - self, - selector: #selector(handleKeyboardNotification(_:)), - name: UIResponder.keyboardWillHideNotification, - object: nil - ) - } - - deinit { - NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil) - NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) - } - - @objc fileprivate func handleKeyboardNotification(_ notification: Notification) { - guard let referenceView = referenceView, - let userInfo = (notification as NSNotification).userInfo, - let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt, - let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double, - let keyboardFrameValue = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue - else { return } - let keyboardFrame = referenceView.convert(keyboardFrameValue.cgRectValue, from: referenceView.window) - let curveOption = UIView.AnimationOptions(rawValue: curve << 16) - let animationOptions = curveOption.union(.beginFromCurrentState) - let baseInset = referenceView.bounds.maxY - keyboardFrame.minY - let inset = max(minimumInset, baseInset) - UIView.performWithoutAnimation { - self.referenceView?.window?.layoutIfNeeded() - } - UIView.animate( - withDuration: duration, - delay: 0, - options: animationOptions, - animations: { self.updateForInset(inset, base: baseInset) }, - completion: nil - ) - } - - /// - /// Do the default actions when the keyboard insets change. - /// - /// The default implementation of this method: - /// - Updates the `scrollView`'s `contentInset.bottom` and `scrollIndicatorInsets.bottom` to that of the `inset` parameter - /// - Sets the `constraint`'s `constant` to the `inset` parameter - /// - Call `layoutIfNeeded` on the reference view - /// - /// - Parameter: - /// - inset: The current keyboard `inset`, clamped by `minimumInset`. - /// - baseInset: The base inset before it is clamped by `minimumInset` - /// - open func updateForInset(_ inset: CGFloat, base baseInset: CGFloat) { - scrollView?.contentInset.bottom = inset - scrollView?.scrollIndicatorInsets.bottom = inset - constraint?.constant = inset - referenceView?.layoutIfNeeded() - } -} -#endif diff --git a/FueledUtils/UIKit/LabelWithTitleAdjustment.swift b/FueledUtils/UIKit/LabelWithTitleAdjustment.swift deleted file mode 100644 index 4b5a59ab..00000000 --- a/FueledUtils/UIKit/LabelWithTitleAdjustment.swift +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import UIKit -import Foundation - -/// -/// A subclass of `UILabel` allowing to easily specify line spacing and kerning. -/// -/// This class exposes properties allowing to customize the title in Interface Builder. -/// Internally, this class works by setting `attributedText`. **Do not use** -/// this class if you're using `attributedText` anywhere. -/// -open class LabelWithTitleAdjustment: UILabel { - /// - /// The line spacing to apply to the label's text. - /// - /// Negative values are **unsupported**. Please refer to the documentation for `NSAttributedString.Key.lineSpacing` for more info. - /// - @IBInspectable public var adjustmentLineSpacing: CGFloat = 0.0 { - didSet { - self.setAdjustedText(self.text) - } - } - - /// - /// The kern value to apply to the label's text. - /// - /// Please refer to the documentation for `NSAttributedString.Key.kernValue` for info about the possible values. - /// - @IBInspectable public var adjustmentKerning: CGFloat = 0.0 { - didSet { - self.setAdjustedText(self.text) - } - } - - /// - /// Please refer to the documentation for `UILabel.text` - /// - override open var text: String? { - get { - return super.text - } - set { - super.text = newValue - self.setAdjustedText(newValue) - } - } - - /// - /// Please refer to the documentation for `UILabel.attributedText` - /// - override open var attributedText: NSAttributedString? { - get { - return super.attributedText - } - set { - super.attributedText = newValue - self.setAdjustedAttributedText(newValue) - } - } - - /// - /// Please refer to the documentation for `UILabel.init(frame:)` - /// - override public init(frame: CGRect) { - super.init(frame: frame) - self.setAdjustedText(self.text) - } - - /// - /// Please refer to the documentation for `UILabel.init(coder:)` - /// - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - self.setAdjustedText(self.text) - } - - private func setAdjustedAttributedText(_ text: NSAttributedString?) { - guard let text = text else { - super.attributedText = nil - return - } - - let paragraphStyle = NSMutableParagraphStyle() - paragraphStyle.lineBreakMode = self.lineBreakMode - paragraphStyle.lineSpacing = self.adjustmentLineSpacing - paragraphStyle.alignment = self.textAlignment - let attributedString = NSMutableAttributedString(attributedString: text) - attributedString.addAttributes( - [ - NSAttributedString.Key.paragraphStyle: paragraphStyle, - NSAttributedString.Key.kern: self.adjustmentKerning, - ], - range: NSRange(location: 0, length: attributedString.string.utf16.count)) - super.attributedText = attributedString - } - - private func setAdjustedText(_ text: String?) { - self.setAdjustedAttributedText(text.map { NSAttributedString(string: $0) }) - } -} -#endif diff --git a/FueledUtils/UIKit/ScrollViewPage.swift b/FueledUtils/UIKit/ScrollViewPage.swift deleted file mode 100644 index 813c2838..00000000 --- a/FueledUtils/UIKit/ScrollViewPage.swift +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import UIKit - -extension UIScrollView { - /// - /// **Unavailable**: Please use `currentPage` instead. - /// - /// Refer to the documentation for `currentPage` for more info. - /// - @available(*, unavailable, renamed: "currentPage") - public var lsd_currentPage: Int { - return self.currentPage - } - - /// - /// **Unavailable**: Please use `numberOfPages` instead. - /// - /// Refer to the documentation for `numberOfPages` for more info. - /// - @available(*, unavailable, renamed: "numberOfPages") - public var lsd_numberOfPages: Int { - return self.numberOfPages - } - - /// - /// **Unavailable**: Please use `setCurrentPage(_:, animated:)` instead. - /// - /// Refer to the documentation for `setCurrentPage(_:, animated:)` for more info. - /// - @available(*, unavailable, renamed: "setCurrentPage(_:animated:)") - public func lsd_setCurrentPage(_ page: Int, animated: Bool) { - self.setCurrentPage(page, animated: animated) - } - - /// - /// Gets/Sets (without animation) the current page of the scroll view, assuming a paginated scroll view of width `self.bounds.size.width`, with no left or right content insets. - /// - /// To set the current page with an animation, use `setCurrentPage(_ page:, animated:)` - /// - /// - Returns: Returns the current page (0-based) - /// - public var currentPage: Int { - get { - let page = Int((self.contentOffset.x / self.bounds.size.width).rounded()) - return min(max(0, page), self.numberOfPages - 1) - } - set { - self.setCurrentPage(newValue, animated: false) - } - } - - /// - /// Gets the total number of pages of the scroll view, assuming a paginated scroll view of width `self.bounds.size.width`, with no left or right content insets. - /// - /// - Returns: Returns the number of pages. - /// - public var numberOfPages: Int { - return Int((self.contentSize.width / self.bounds.size.width).rounded(.up)) - } - - /// - /// Sets the current page of the scroll view, assuming a paginated scroll view of width `self.bounds.size.width`, with no left or right content insets. - /// - /// - Parameters: - /// - page: The page to set to. - /// - animated: Whether to animate the change or not. - /// - public func setCurrentPage(_ page: Int, animated: Bool) { - let offset = CGPoint(x: self.bounds.size.width * CGFloat(page), y: 0) - self.setContentOffset(offset, animated: animated) - } -} -#endif diff --git a/FueledUtils/UIKit/SetRootViewController.swift b/FueledUtils/UIKit/SetRootViewController.swift deleted file mode 100644 index b1208b9e..00000000 --- a/FueledUtils/UIKit/SetRootViewController.swift +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import Foundation -import UIKit - -extension UIApplicationDelegate { - /// - /// Switches root view controller avoiding common problems of unintended animations. - /// - /// - Parameters: - /// - viewController: The new view controller to swift to. - /// - setWindow: If `self.window` is `nil`, this closure will be executed - /// - completion: The completion block to execute when the transition is completed. - /// - public func setRootViewController(_ viewController: UIViewController, setWindow: ((UIWindow) -> Void)? = nil, completion: (() -> Void)? = nil) { - if let window = self.window.flatMap({ $0 }) { - UIView.transition( - with: window, - duration: 0.33, - options: .transitionCrossDissolve, - animations: { - UIView.setAnimationsEnabled(false) - window.endEditing(true) - - window.rootViewController = viewController - window.layoutIfNeeded() - UIView.setAnimationsEnabled(true) - }, - completion: { _ in - completion?() - } - ) - } else { - let window = UIWindow(frame: UIScreen.main.bounds) - setWindow?(window) - window.rootViewController = viewController - window.makeKeyAndVisible() - completion?() - } - } -} -#endif diff --git a/FueledUtils/UIKit/UIExtensions.swift b/FueledUtils/UIKit/UIExtensions.swift deleted file mode 100644 index 614a2c44..00000000 --- a/FueledUtils/UIKit/UIExtensions.swift +++ /dev/null @@ -1,667 +0,0 @@ -// Copyright © 2020, Fueled Digital Media, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if canImport(UIKit) && !os(watchOS) -import Foundation -import UIKit - -extension CGSize { - /// - /// Scale the recipient to the given size, according to the specified content mode. - /// - /// This methods is best use in combination of `UIImage.resized`, to make sure that the image - /// is scaled properly for your needs. - /// - /// - Parameters: - /// - size: The size to scale the receiver to. - /// - contentMode: The content mode to use when scaling the receiver. - /// If `contentMode` is `.scaleAspectFill`, the method will try to maximize the lowest dimension of the receiver - /// to the lowest dimension of `size`. - /// If `contentMode` is `.scaleAspectFit`, the method will try to maximize the highest dimension of the receiver - /// to the lowest dimension of `size`. - /// If the `contentMode` is `redraw` or `scaleToFill` (the default), `size` is returned. - /// In all other cases, the receiver is returned and `size` is ignored. - /// - Returns: The scaled size as specified by the parameters. - /// - public func scaled(to size: CGSize, contentMode: UIView.ContentMode = .scaleToFill) -> CGSize { - switch contentMode { - case .redraw, - .scaleToFill: - return size - case .scaleAspectFill: - let aspectRatio = self.width / self.height - if self.width < self.height { - return CGSize(width: size.width, height: size.width / aspectRatio) - } else { - return CGSize(width: size.width * aspectRatio, height: size.height) - } - case .scaleAspectFit: - let aspectRatio = self.width / self.height - if self.width < self.height { - return CGSize(width: size.width, height: size.width / aspectRatio) - } else { - return CGSize(width: size.width * aspectRatio, height: size.height) - } - default: - return self - } - } -} - -extension UIColor { - /// - /// Initialize a color using a 32-bits integr that represents a color, and an optional alpha component. - /// Only the right-most 24-bits are used, the left-most 8 bits are ignored. - /// - /// It is recommended to always include the leading zeros when using a literal color, so as to prevent confusion. - /// ```swift - /// UIColor(hex: 0x0000FF) // blue color - /// ``` - /// rather than: - /// ```swift - /// UIColor(hex: 0xFF) // blue color - /// ``` - /// - /// ## Examples - /// ```swift - /// UIColor(hex: 0xFF0000) // red color - /// UIColor(hex: 0x00FF00) // green color - /// UIColor(hex: 0x0000FF) // blue color - /// ``` - /// - /// - Parameters: - /// - hex: The hexadecimal value to use when initializing the color. The left-most 8 bits are ignored. - /// - alpha: The alpha value to use when initializing the color. Defaults to `1` - /// - public convenience init(hex: UInt32, alpha: CGFloat = 1) { - func byteColor(_ x: UInt32) -> CGFloat { - return CGFloat(x & 0xFF) / 255 - } - let red = byteColor(hex >> 16) - let green = byteColor(hex >> 8) - let blue = byteColor(hex) - self.init(red: red, green: green, blue: blue, alpha: alpha) - } - - /// - /// Initialize a color using a hexadecimal string (case insensitive), with an optional `#` or `0x` prefix. - /// - /// ## Examples - /// ```swift - /// UIColor(hexString: "FF0000") // red color - /// UIColor(hexString: "#00ff00") // green color - /// UIColor(hexString: "0x0000FF") // blue color - /// UIColor(hexString: "0x0000FG") // nil - /// UIColor(hexString: "FF000") // nil - /// UIColor(hexString: "#FF000") // nil - /// UIColor(hexString: "0xFF000") // nil - /// ``` - /// - /// - Parameters: - /// - hexString: The hexadecimal string to use when initializing the color. The string may start with `0x` and `#` and then must contain exactly 6 characters. - /// Any invalid characters will result in the initializer failed. - /// - alpha: The alpha value to use when initializing the color. Defaults to `1` - /// - public convenience init?(hexString: String, alpha: CGFloat = 1) { - let regex = try! NSRegularExpression(pattern: "\\A(?:0x|#)?([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])\\Z", options: [.caseInsensitive]) - guard let match = regex.firstMatch(in: hexString, options: [], range: hexString.nsRange), match.numberOfRanges == 4 else { - return nil - } - let redString = (hexString as NSString).substring(with: match.range(at: 1)) - let greenString = (hexString as NSString).substring(with: match.range(at: 2)) - let blueString = (hexString as NSString).substring(with: match.range(at: 3)) - guard let red = Int(redString, radix: 16), let green = Int(greenString, radix: 16), let blue = Int(blueString, radix: 16) else { - return nil - } - self.init(red: CGFloat(red) / 255, green: CGFloat(green) / 255, blue: CGFloat(blue) / 255, alpha: alpha) - } -} - -extension UILabel { - /// - /// Add the monospaced number font descriptor to the current `font`. - /// - public func useMonospacedNumbers() { - let fontDescriptor = self.font.fontDescriptor - let newFontDescriptor = fontDescriptor.addingAttributes([ - UIFontDescriptor.AttributeName.featureSettings: [ - [ - UIFontDescriptor.FeatureKey.featureIdentifier: kNumberSpacingType, - UIFontDescriptor.FeatureKey.typeIdentifier: kMonospacedNumbersSelector, - ], - ], - ]) - self.font = UIFont(descriptor: newFontDescriptor, size: self.font.pointSize) - } - - /// - /// Allows to set the text and optionally animate the change. - /// - /// - Parameters: - /// - string: The text to set - /// - animated: Whether to animate the change or not. If `false`, the method call is equivalent to using the setter `text` - /// - public func setText(_ string: String?, animated: Bool) { - if !animated { - self.text = string - return - } - UIView.transition(with: self, duration: 0.35, options: .transitionCrossDissolve, animations: { - self.text = string - }, completion: nil) - } - - /// - /// Allows to set an attributed text and optionally animate the change. - /// - /// - Parameters: - /// - attributedString: The attributed string to set - /// - animated: Whether to animate the change or not. If `false`, the method call is equivalent to using the setter `attributedText` - /// - public func setAttributedText(_ attributedString: NSAttributedString, animated: Bool) { - if !animated { - self.attributedText = attributedString - return - } - UIView.transition(with: self, duration: 0.35, options: .transitionCrossDissolve, animations: { - self.attributedText = attributedString - }, completion: nil) - } -} - -extension UIActivityIndicatorView { - /// - /// **Unavailable**: Please use `animating` instead. - /// - /// Refer to the documentation for `animating` for more info. - /// - @available(*, unavailable, renamed: "animating") - public var fueled_animating: Bool { - get { - return self.animating - } - set { - self.animating = newValue - } - } - - /// - /// Get/Set the animating state of the `UIActivityIndicatorView`. - /// - public var animating: Bool { - get { - return self.isAnimating - } - set { - if newValue { - self.startAnimating() - } else { - self.stopAnimating() - } - } - } -} - -extension UITextField { - /// - /// Allows to set the placeholder color by setting the `attributedPlaceholder`. - /// - /// - Warning: The getter must not be used or the code will crash at runtime. - /// - @IBInspectable public var placeholderColor: UIColor? { - get { - fatalError("Getter for UITextField.placeholderColor is not implemented") - } - set { - if let color = newValue, let placeholder = self.placeholder { - attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [ - NSAttributedString.Key.foregroundColor: color, - ]) - } - } - } -} - -extension UIView { - /// - /// Adds the given subview into the receiver, and adds constraint so that its top, bottom, left and right's edges are bounds to its superview's edges. - /// - Parameters: - /// - insets: Optionally apply an offset when adding the view. - /// - Returns: The image if it could be generated. If it couldn't, for example if the `UIView`'s width or height is 0, a crash will happen at runtime. - /// - /// - Note: The returns is an implicitely unwrapped optional for backward-compatibility purpose, and will be made an optional in a future release (as well as not crash) - /// - public func addAndFitSubview(_ view: UIView, insets: UIEdgeInsets = .zero) { - view.translatesAutoresizingMaskIntoConstraints = false - view.frame = self.bounds.inset(by: insets) - self.addSubview(view) - self.addConstraints( - [ - NSLayoutConstraint(item: view, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: insets.left), - NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: -insets.right), - NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: insets.top), - NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: -insets.bottom), - ] - ) - } - - /// - /// Take a snapshot of the view and returns a `UIImage`. - /// - /// - Parameters: - /// - afterScreenUpdates: Please refer to the documentation for `afterScreenUpdates` in `UIView.drawHierarchy(in:, afterScreenUpdates:)` for more info. - /// - Returns: The image if it could be generated. If it couldn't, for example if the `UIView`'s width or height is 0, a crash will happen at runtime. - /// - /// - Note: The returns is an implicitely unwrapped optional for backward-compatibility purpose, and will be made an optional in a future release (as well as not crash) - /// - public func snapshotImage(afterScreenUpdates: Bool = true) -> UIImage! { - return UIImage.draw(size: self.bounds.size) { _ in - self.drawHierarchy(in: self.bounds, afterScreenUpdates: afterScreenUpdates) - } - } - - /// - /// Renders the view's layer and its sublayers and returns a `UIImage`. In contrast with `snapshotImage(afterScreenUpdates:)` which works only for visible onscreen content - /// it works even in cases when the view's `draw(_:)` method hasn't been called yet at the moment of calling the method. - /// - /// - Parameters: - /// - opaque: Please refer to the parameters documentation for `UIGraphicsBeginImageContextWithOptions` for more info. - /// - scale: Please refer to the parameters documentation for `UIGraphicsBeginImageContextWithOptions` for more info. - /// - Returns: The image if it could be generated. If it couldn't, for example if the `UIView`'s width or height is 0, a crash will happen at runtime. - /// - /// - Note: The returns is an implicitely unwrapped optional for backward-compatibility purpose, and will be made an optional in a future release (as well as not crash) - /// - public func renderToImage(opaque: Bool = false, scale: CGFloat = 0.0) -> UIImage { - return UIImage.draw(size: self.bounds.size, opaque: opaque, scale: scale) { context in - self.layer.render(in: context) - } - } - - /// - /// Apply a shadow with the parameters that can be specified in the Sketch application. - /// This methods internally updates the following properties of the backing `CALayer` (`self.layer`): - /// - `CALayer.shadowColor` - /// - `CALayer.shadowOpacity` - /// - `CALayer.shadowOffset` - /// - `CALayer.shadowRadius` - /// - `CALayer.shadowPath` - /// - /// When using this method, it is recommended **not** to modify any of these properties to avoid unexpected results. - /// - /// - Parameters: - /// - color: The color of the shadow, as specified in Sketch (usually without the alpha component, specified afterwards) - /// - alpha: The alpha (opacity) of the shadow, as specified in Sketch - /// - xAxis: The X direction of the shadow, as specified in Sketch - /// - yAxis: The y direction of the shadow, as specified in Sketch - /// - blur: The blur offset of the shadow, as specified in Sketch - /// - spread: The spread of the shadow, as specified in Sketch. - /// - path: The path the shadow should use. If `nil`, it defaults to a rectangle of the size of the bounds of the receiver - /// - /// - Note: It is safe to call this method multiple times without calling `removeSketchShadow` between each calls. - /// - public func applySketchShadow( - color: UIColor = .black, - alpha: Float = 0.5, - xAxis: CGFloat = 0.0, - yAxis: CGFloat = 2.0, - blur: CGFloat = 4.0, - spread: CGFloat = 0.0, - path: CGPath? = nil) - { - self.layer.shadowColor = color.cgColor - self.layer.shadowOpacity = alpha - self.layer.shadowOffset = CGSize(width: xAxis, height: yAxis) - self.layer.shadowRadius = blur / 2.0 - - if path == nil || spread == 0.0 { - self.layer.shadowPath = nil - } else { - let scaleFactor = (self.bounds.size.width + spread * 2.0) / self.bounds.size.width - let path = (path.map { UIBezierPath(cgPath: $0) } ?? UIBezierPath(rect: self.bounds)) - path.apply(CGAffineTransform(scaleX: scaleFactor, y: scaleFactor)) - self.layer.shadowPath = path.cgPath - } - } - - /// - /// Remove a shadow as set by `applySketchShadow` - /// This method will reset any shadows sets on the backing layer, _even it wasn't applied by `applySketchShadow` - /// - public func removeSketchShadow() { - self.layer.shadowColor = nil - self.layer.shadowOpacity = 0.0 - self.layer.shadowOffset = .zero - self.layer.shadowRadius = 0.0 - self.layer.shadowPath = nil - } -} - -@available(iOS 9.0, *) -extension UIStackView { - /// - /// Removes all of the current arranged subviews from the `UIStackView`, optionally - /// allowing to remove them from the `UIStackView`'s subviews as well. - /// - /// - Parameters: - /// - removeFromHierachy: If `true`, each views is also removed from the receiver using `removeFromSuperview()`. - /// If `false`, `removeFromSuperview()` is not called. - /// This parameters defaults to `true`. - /// - public func removeArrangedSubviews(removeFromHierachy: Bool = true) { - let arrangedSubviews = self.arrangedSubviews - arrangedSubviews.forEach { self.removeArrangedSubview($0, removeFromHierachy: removeFromHierachy) } - } - - /// - /// Removes the given arranged subview from the `UIStackView`, optionally - /// allowing to remove it from the `UIStackView`'s subviews as well. - /// - /// - Parameters: - /// - view: The arranged subview to remove from the receiver. - /// - removeFromHierachy: If `true`, the view is also removed from the receiver using `removeFromSuperview()`. - /// If `false`, `removeFromSuperview()` is not called. - /// - public func removeArrangedSubview(_ view: UIView, removeFromHierachy: Bool) { - if removeFromHierachy { - view.removeFromSuperview() - } else { - // `removeArrangedSubview` doesn't call `removeFromSuperview` for the `view` - self.removeArrangedSubview(view) - } - } -} - -extension UITableView { - /// - /// Deselect the given rows, optionally with an animation. - /// - /// - Parameters: - /// - indexPaths: The rows to deselect. - /// - animated: `true` if you want to animate the deselection, and `false` if the change should be immediate. - /// - public func deselectRows(_ indexPaths: [IndexPath], animated: Bool) { - for indexPath in indexPaths { - self.deselectRow(at: indexPath, animated: animated) - } - } - - /// - /// **Unavailable**: Please use `deselectAllRows(animated:)` instead. - /// - /// Refer to the documentation for `deselectAllRows(animated:)` for more info. - /// - @available(*, unavailable, renamed: "deselectAllRows(animated:)") - public func deselectAllRows(_ animated: Bool) { - self.deselectAllRows(animated: animated) - } - - /// - /// Deselect all currently selected rows, optionally with an animation. - /// - /// - Parameters: - /// - animated: `true` if you want to animate the deselection, and `false` if the change should be immediate. - /// - public func deselectAllRows(animated: Bool) { - if let indexPaths = self.indexPathsForSelectedRows { - self.deselectRows(indexPaths, animated: animated) - } - } -} - -extension UICollectionView { - /// - /// Deselect the given items, optionally with an animation. - /// - /// - Parameters: - /// - indexPaths: The items to deselect. - /// - animated: `true` if you want to animate the deselection, and `false` if the change should be immediate. - /// - public func deselectItems(_ indexPaths: [IndexPath], animated: Bool) { - for indexPath in indexPaths { - self.deselectItem(at: indexPath, animated: animated) - } - } - - /// - /// **Unavailable**: Please use `deselectAllItems(animated:)` instead. - /// - /// Refer to the documentation for `deselectAllItems(animated:)` for more info. - /// - @available(*, unavailable, renamed: "deselectAllItems(animated:)") - public func deselectAllItems(_ animated: Bool) { - self.deselectAllItems(animated: animated) - } - - /// - /// Deselect all currently selected rows, optionally with an animation. - /// - /// - Parameters: - /// - animated: `true` if you want to animate the deselection, and `false` if the change should be immediate. - /// - public func deselectAllItems(animated: Bool) { - if let indexPaths = self.indexPathsForSelectedItems { - self.deselectItems(indexPaths, animated: animated) - } - } -} - -extension UIImage { - /// - /// Create a `CGContext` allowing to do custom drawing, and returns the resulting image as drawn in the context. - /// - Parameters: - /// - size: Please refer to the parameters documentation for `UIGraphicsBeginImageContextWithOptions` for more info. - /// - opaque: Please refer to the parameters documentation for `UIGraphicsBeginImageContextWithOptions` for more info. - /// - scale: Please refer to the parameters documentation for `UIGraphicsBeginImageContextWithOptions` for more info. - /// - graphics: The drawing actions to execute. - /// - public static func draw(size: CGSize, opaque: Bool = false, scale: CGFloat = 0.0, graphics: (CGContext) -> Void) -> UIImage { - var image: UIImage! - autoreleasepool { - UIGraphicsBeginImageContextWithOptions(size, opaque, scale) - graphics(UIGraphicsGetCurrentContext()!) - image = UIGraphicsGetImageFromCurrentImageContext() - UIGraphicsEndImageContext() - } - return image - } - - /// - /// **Unavailable**: Please use `withAlpha(_:)` instead. - /// - /// Refer to the documentation for `withAlpha(_:)` for more info. - /// - @available(*, unavailable, renamed: "withAlpha(_:)") - public func imageWithAlpha(_ alpha: CGFloat) -> UIImage { - return self.withAlpha(alpha) - } - - /// - /// Returns the receiver with the given alpha applied to it. The rendering mode is kept the same. - /// The resulting image will be made resizable whether it was originally or not, - /// with `capInsets` set as the cap insets, and `resizingMode` as its resizing mode. - /// - /// - Parameters: - /// - alpha: The alpha to apply to the receiver. - /// - public func withAlpha(_ alpha: CGFloat) -> UIImage { - let rect = CGRect(origin: .zero, size: self.size) - let image = UIImage.draw(size: self.size, opaque: false, scale: self.scale) { _ in - self.draw(in: rect, blendMode: .normal, alpha: alpha) - } - return image.resizableImage(withCapInsets: self.capInsets, resizingMode: self.resizingMode).withRenderingMode(self.renderingMode) - } - - /// - /// **Unavailable**: Please use `withTint(_:)` instead. - /// - /// Refer to the documentation for `withTint(_:)` for more info. - /// - @available(*, unavailable, renamed: "withTint(_:)") - public func imageTintedWithColor(_ color: UIColor) -> UIImage { - return self.withTint(color) - } - - /// - /// Apply the given tint to the image. The rendering mode is kept the same. - /// This method takes the rgb values of each pixels in the image, and replace them with the color - /// given as parameter. The alpha value of each pixels is kept the same. - /// The resulting image will be made resizable whether it was originally or not, - /// with `capInsets` set as the cap insets, and `resizingMode` as its resizing mode. - /// - /// The behavior of this method is similar to using the `UIImage` with a `.alwaysTemplate` rendering mode - /// and using a `tintColor` when displaying the `UIImage` in an `UIImageView`. - /// - /// - SeeAlso: `withColor(_:)` - /// - /// - Parameters: - /// - tint: The tint to apply to the receiver. - /// - public func withTint(_ tint: UIColor) -> UIImage { - let image = UIImage.draw(size: self.size, scale: self.scale) { _ in - tint.setFill() - UIRectFill(CGRect(origin: .zero, size: self.size)) - self.draw(at: .zero, blendMode: .destinationIn, alpha: 1) - } - return image.resizableImage(withCapInsets: self.capInsets, resizingMode: self.resizingMode).withRenderingMode(self.renderingMode) - } - - /// - /// Apply the given color to the image. The rendering mode is kept the same. - /// This method keeps the brightness of all pixels the same, but updates the saturation and hue - /// to that of the given color. - /// - /// In other words, this methods can be used to color grayscale images or tint images without loosing - /// contrast information. - /// - /// - SeeAlso: `withTint(_:)` - /// - /// - Parameters: - /// - color: The color to apply to the receiver. - /// - public func withColor(_ color: UIColor) -> UIImage { - return UIImage.draw( - size: self.size, - graphics: { context in - let rect = CGRect(origin: .zero, size: self.size) - self.draw(in: rect, blendMode: .color, alpha: 1.0) - context.setFillColor(color.cgColor) - context.setBlendMode(.color) - context.fill(rect) - } - ).withRenderingMode(self.renderingMode) - } - - /// - /// Apply the given tint to the image. The rendering mode is kept the same. - /// - /// - Parameters: - /// - offset: The offset to apply to the original image in the resulting image. - /// - contextSize: The size of the context used to resize the image. If not specified, it defaults to `CGSize(width: offset.x + size.width, height: offset.y + size.height)` - /// - size: The size to resize the image to. - /// - public func resized(offset: CGPoint = .zero, contextSize: CGSize? = nil, size: CGSize) -> UIImage? { - let contextSize = contextSize ?? CGSize(width: offset.x + size.width, height: offset.y + size.height) - return UIImage.draw(size: contextSize) { _ in - self.draw(in: CGRect(origin: offset, size: size)) - }.withRenderingMode(self.renderingMode) - } - - /// - /// **Unavailable**: Please use `ofColor(_:)` instead. - /// - /// Refer to the documentation for `ofColor(_:)` for more info. - /// - @available(*, unavailable, renamed: "ofColor(_:)") - public static func imageWithColor(_ color: UIColor) -> UIImage { - return self.ofColor(color) - } - - /// - /// Create a 1px image with the given color. - /// - /// - Parameters: - /// - color: The of the image to create - /// - public static func ofColor(_ color: UIColor) -> UIImage { - let size = CGSize(width: 1, height: 1) - - let image = UIImage.draw(size: size, scale: 1) { _ in - color.setFill() - UIRectFill(CGRect(origin: .zero, size: size)) - } - return image - } - - /// - /// **Unavailable**: Please use `roundedRectStretchableImage(borderColor:, fillColor:, borderWidth:, cornerRadius:, scale:)` instead. - /// Create an stretchable rectangle with rounded corners image, with the given parameters. - /// - /// - Parameters: - /// - borderColor: The border color to use for the rectangle. - /// - backgroundColor: The color to use to fill the rectangle. - /// - lineWidth: The width of the border. - /// - radius: The radius of the corners of the rectangle. `0` means the rectangle will not have rounded corners. - /// - scale: Please refer to the parameters documentation for `UIGraphicsBeginImageContextWithOptions` for more info. - /// - Returns: The generated stretchable rectangle with rounded corners, with the given parameters. - /// - @available(*, unavailable, renamed: "roundedRectStretchableImage(borderColor:borderWidth:fillColor:cornerRadius:scale:)") - public static func roundedRectStretchableImage( - borderColor: UIColor, - backgroundColor: UIColor = .clear, - lineWidth: CGFloat, - radius: CGFloat, - scale: CGFloat = 0.0) - -> UIImage - { - return self.roundedRectStretchableImage(borderColor: borderColor, borderWidth: lineWidth, fillColor: backgroundColor, cornerRadius: radius, scale: scale) - } - - /// - /// Create an stretchable rectangle with rounded corners image, with the given parameters. - /// - /// - Parameters: - /// - borderColor: The border color to use for the rectangle. - /// - borderWidth: The width of the border. - /// - fillColor: The color to use to fill the rectangle. - /// - cornerRadius: The radius of the corners of the rectangle. `0` means the rectangle will not have rounded corners. - /// - scale: Please refer to the parameters documentation for `UIGraphicsBeginImageContextWithOptions` for more info. - /// - Returns: The generated stretchable rectangle with rounded corners, with the given parameters. - /// - public static func roundedRectStretchableImage( - borderColor: UIColor, - borderWidth: CGFloat, - fillColor: UIColor = .clear, - cornerRadius: CGFloat, - scale: CGFloat = 0.0) - -> UIImage - { - let stretchableAreaSize: CGFloat = 1 - let canvasSize = CGSize(width: cornerRadius * 2 + stretchableAreaSize, height: cornerRadius * 2 + stretchableAreaSize) - let roundedRectSize = CGSize(width: canvasSize.width - borderWidth, height: canvasSize.height - borderWidth) - - let image = UIImage.draw(size: canvasSize, scale: scale) { _ in - fillColor.setFill() - borderColor.setStroke() - - let bezierPath = UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: borderWidth / 2, y: borderWidth / 2), size: roundedRectSize), cornerRadius: cornerRadius) - bezierPath.lineWidth = borderWidth - bezierPath.fill() - bezierPath.stroke() - } - - let capInset = cornerRadius + borderWidth / 2 - return image.resizableImage(withCapInsets: .init(top: capInset, left: capInset, bottom: capInset, right: capInset), resizingMode: .stretch) - } -} -#endif diff --git a/Package.swift b/Package.swift index e0c885cd..37285229 100644 --- a/Package.swift +++ b/Package.swift @@ -13,26 +13,10 @@ let package = Package( name: "FueledUtilsCore", targets: ["FueledUtilsCore"] ), - .library( - name: "FueledUtilsReactiveCommon", - targets: ["FueledUtilsReactiveCommon"] - ), - .library( - name: "FueledUtilsUIKit", - targets: ["FueledUtilsUIKit"] - ), .library( name: "FueledUtilsCombine", targets: ["FueledUtilsCombine"] ), - .library( - name: "FueledUtilsCombineOperators", - targets: ["FueledUtilsCombineOperators"] - ), - .library( - name: "FueledUtilsCombineUIKit", - targets: ["FueledUtilsCombineUIKit"] - ), .library( name: "FueledUtilsSwiftUI", targets: ["FueledUtilsSwiftUI"] @@ -45,57 +29,43 @@ let package = Package( targets: [ .target( name: "FueledUtilsCore", - path: "FueledUtils/Core", + path: "Sources/FueledUtils/Core", linkerSettings: [ .linkedFramework("Foundation") - ] - ), - .target( - name: "FueledUtilsReactiveCommon", - dependencies: ["FueledUtilsCore"], - path: "FueledUtils/ReactiveCommon" - ), - .target( - name: "FueledUtilsUIKit", - dependencies: ["FueledUtilsCore"], - path: "FueledUtils/UIKit", - linkerSettings: [ - .linkedFramework("Foundation"), - .linkedFramework("UIKit", .when(platforms: [.iOS, .tvOS])), - .linkedFramework("AppKit", .when(platforms: [.macOS])), ] ), .target( name: "FueledUtilsCombine", - dependencies: ["FueledUtilsReactiveCommon"], - path: "FueledUtils/Combine" - ), - .target( - name: "FueledUtilsCombineOperators", - dependencies: ["FueledUtilsCombine"], - path: "FueledUtils/CombineOperators" - ), - .target( - name: "FueledUtilsCombineUIKit", - dependencies: ["FueledUtilsCombine", "FueledUtilsUIKit"], - path: "FueledUtils/CombineUIKit" + dependencies: [ + "FueledUtilsCore" + ], + path: "Sources/FueledUtils/Combine" ), .target( name: "FueledUtilsSwiftUI", dependencies: ["FueledUtilsCombine", "FueledUtilsCore"], - path: "FueledUtils/SwiftUI", + path: "Sources/FueledUtils/SwiftUI", linkerSettings: [ .linkedFramework("SwiftUI", .when(platforms: [.iOS, .tvOS, .macOS])), ] ), .testTarget( - name: "FueledUtils", + name: "FueledUtilsCoreTests", dependencies: [ - "FueledUtilsCombineUIKit", + "FueledUtilsCore", "Quick", "Nimble", ], - path: "Tests/Tests" + path: "Tests/FueledUtils/CoreTests" + ), + .testTarget( + name: "FueledUtilsCombineTests", + dependencies: [ + "FueledUtilsCombine", + "Quick", + "Nimble", + ], + path: "Tests/FueledUtils/CombineTests" ), ] ) diff --git a/FueledUtils/Combine/Action.swift b/Sources/FueledUtils/Combine/Action.swift similarity index 98% rename from FueledUtils/Combine/Action.swift rename to Sources/FueledUtils/Combine/Action.swift index fe42255f..d2a79b5d 100644 --- a/FueledUtils/Combine/Action.swift +++ b/Sources/FueledUtils/Combine/Action.swift @@ -12,12 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) import Combine -#if canImport(FueledUtilsReactiveCommon) import FueledUtilsCore -import FueledUtilsReactiveCommon -#endif @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public final class Action { @@ -200,5 +196,3 @@ extension Action { return action } } - -#endif diff --git a/FueledUtils/Combine/ActionError.swift b/Sources/FueledUtils/Combine/ActionError.swift similarity index 100% rename from FueledUtils/Combine/ActionError.swift rename to Sources/FueledUtils/Combine/ActionError.swift diff --git a/FueledUtils/ReactiveCommon/ActionErrorProtocol.swift b/Sources/FueledUtils/Combine/ActionErrorProtocol.swift similarity index 100% rename from FueledUtils/ReactiveCommon/ActionErrorProtocol.swift rename to Sources/FueledUtils/Combine/ActionErrorProtocol.swift diff --git a/FueledUtils/Combine/ActionProtocol.swift b/Sources/FueledUtils/Combine/ActionProtocol.swift similarity index 100% rename from FueledUtils/Combine/ActionProtocol.swift rename to Sources/FueledUtils/Combine/ActionProtocol.swift diff --git a/FueledUtils/Combine/AnyAction.swift b/Sources/FueledUtils/Combine/AnyAction.swift similarity index 100% rename from FueledUtils/Combine/AnyAction.swift rename to Sources/FueledUtils/Combine/AnyAction.swift diff --git a/FueledUtils/Combine/AnyCurrentValuePublisher.swift b/Sources/FueledUtils/Combine/AnyCurrentValuePublisher.swift similarity index 100% rename from FueledUtils/Combine/AnyCurrentValuePublisher.swift rename to Sources/FueledUtils/Combine/AnyCurrentValuePublisher.swift diff --git a/FueledUtils/Combine/CoalescingAction.swift b/Sources/FueledUtils/Combine/CoalescingAction.swift similarity index 98% rename from FueledUtils/Combine/CoalescingAction.swift rename to Sources/FueledUtils/Combine/CoalescingAction.swift index 57c70ec0..b6761ab7 100644 --- a/FueledUtils/Combine/CoalescingAction.swift +++ b/Sources/FueledUtils/Combine/CoalescingAction.swift @@ -12,12 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) import Combine -#if canImport(FueledUtilsReactiveCommon) import FueledUtilsCore -import FueledUtilsReactiveCommon -#endif /// /// Similar to `Action`, except if the action is already executing, subsequent `apply()` call will not fail, @@ -153,5 +149,3 @@ public class CoalescingAction: ActionProtoc .eraseToAnyPublisher() } } - -#endif diff --git a/FueledUtils/Combine/CombineExtensions+Cancellables.swift b/Sources/FueledUtils/Combine/CombineExtensions+Cancellables.swift similarity index 93% rename from FueledUtils/Combine/CombineExtensions+Cancellables.swift rename to Sources/FueledUtils/Combine/CombineExtensions+Cancellables.swift index 7532e42d..3e0487a0 100644 --- a/FueledUtils/Combine/CombineExtensions+Cancellables.swift +++ b/Sources/FueledUtils/Combine/CombineExtensions+Cancellables.swift @@ -12,13 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) import Combine -#if canImport(FueledUtilsReactiveCommon) import Foundation import FueledUtilsCore -import FueledUtilsReactiveCommon -#endif private var cancellablesKey: UInt8 = 0 @@ -54,5 +50,3 @@ extension CombineExtensions { } } } - -#endif diff --git a/FueledUtils/Combine/CombineExtensions.swift b/Sources/FueledUtils/Combine/CombineExtensions.swift similarity index 100% rename from FueledUtils/Combine/CombineExtensions.swift rename to Sources/FueledUtils/Combine/CombineExtensions.swift diff --git a/FueledUtils/CombineOperators/Combine+Operators.swift b/Sources/FueledUtils/Combine/CombineOperators/Combine+Operators.swift similarity index 96% rename from FueledUtils/CombineOperators/Combine+Operators.swift rename to Sources/FueledUtils/Combine/CombineOperators/Combine+Operators.swift index 9d521a82..5f5952ba 100644 --- a/FueledUtils/CombineOperators/Combine+Operators.swift +++ b/Sources/FueledUtils/Combine/CombineOperators/Combine+Operators.swift @@ -12,18 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) import Combine -#if canImport(FueledUtilsCombine) -import FueledUtilsCombine import FueledUtilsCore -import FueledUtilsReactiveCommon + public typealias OptionalProtocol = FueledUtilsCore.OptionalProtocol -#endif // swiftlint:disable generic_type_name -#if !canImport(ReactiveSwift) precedencegroup BindingPrecedence { associativity: right @@ -31,9 +26,6 @@ precedencegroup BindingPrecedence { } infix operator <~: BindingPrecedence -#else -import ReactiveSwift -#endif precedencegroup AccessPrecedence { associativity: right @@ -135,5 +127,3 @@ public func >>> (lhs: AnyCanc public func >>> (lhs: AnyCancellable, rhs: inout Set) { lhs.store(in: &rhs) } - -#endif diff --git a/FueledUtils/CombineOperators/CombineOperators+Optional.swift b/Sources/FueledUtils/Combine/CombineOperators/CombineOperators+Optional.swift similarity index 100% rename from FueledUtils/CombineOperators/CombineOperators+Optional.swift rename to Sources/FueledUtils/Combine/CombineOperators/CombineOperators+Optional.swift diff --git a/FueledUtils/Combine/NSObject+CombineExtensions.swift b/Sources/FueledUtils/Combine/NSObject+CombineExtensions.swift similarity index 100% rename from FueledUtils/Combine/NSObject+CombineExtensions.swift rename to Sources/FueledUtils/Combine/NSObject+CombineExtensions.swift diff --git a/FueledUtils/Combine/ObservableObjectExtensions.swift b/Sources/FueledUtils/Combine/ObservableObjectExtensions.swift similarity index 96% rename from FueledUtils/Combine/ObservableObjectExtensions.swift rename to Sources/FueledUtils/Combine/ObservableObjectExtensions.swift index 254772d9..a29ad4ca 100644 --- a/FueledUtils/Combine/ObservableObjectExtensions.swift +++ b/Sources/FueledUtils/Combine/ObservableObjectExtensions.swift @@ -12,13 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) import Combine -#if canImport(FueledUtilsReactiveCommon) import Foundation import FueledUtilsCore -import FueledUtilsReactiveCommon -#endif @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension ObservableObject where Self.ObjectWillChangePublisher == ObservableObjectPublisher { @@ -99,5 +95,3 @@ extension Publisher where Output: Collection, Failure == Never, Output.Element: self.flatMap { Publishers.CombineLatestMany($0.map { $0.publisher }) }.eraseToAnyPublisher() } } - -#endif diff --git a/FueledUtils/Combine/OverridingAction.swift b/Sources/FueledUtils/Combine/OverridingAction.swift similarity index 100% rename from FueledUtils/Combine/OverridingAction.swift rename to Sources/FueledUtils/Combine/OverridingAction.swift diff --git a/FueledUtils/Combine/Published+PublisherInit.swift b/Sources/FueledUtils/Combine/Published+PublisherInit.swift similarity index 100% rename from FueledUtils/Combine/Published+PublisherInit.swift rename to Sources/FueledUtils/Combine/Published+PublisherInit.swift diff --git a/FueledUtils/Combine/Publisher+AdditionalHandleEvents.swift b/Sources/FueledUtils/Combine/Publisher+AdditionalHandleEvents.swift similarity index 100% rename from FueledUtils/Combine/Publisher+AdditionalHandleEvents.swift rename to Sources/FueledUtils/Combine/Publisher+AdditionalHandleEvents.swift diff --git a/FueledUtils/Combine/Publisher+CombinePrevious.swift b/Sources/FueledUtils/Combine/Publisher+CombinePrevious.swift similarity index 100% rename from FueledUtils/Combine/Publisher+CombinePrevious.swift rename to Sources/FueledUtils/Combine/Publisher+CombinePrevious.swift diff --git a/FueledUtils/Combine/Publisher+IgnoreRepeats.swift b/Sources/FueledUtils/Combine/Publisher+IgnoreRepeats.swift similarity index 100% rename from FueledUtils/Combine/Publisher+IgnoreRepeats.swift rename to Sources/FueledUtils/Combine/Publisher+IgnoreRepeats.swift diff --git a/FueledUtils/Combine/Publisher+TransferState.swift b/Sources/FueledUtils/Combine/Publisher+TransferState.swift similarity index 91% rename from FueledUtils/Combine/Publisher+TransferState.swift rename to Sources/FueledUtils/Combine/Publisher+TransferState.swift index 2243e01c..8fa21ca5 100644 --- a/FueledUtils/Combine/Publisher+TransferState.swift +++ b/Sources/FueledUtils/Combine/Publisher+TransferState.swift @@ -12,12 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) import Combine -#if canImport(FueledUtilsReactiveCommon) import FueledUtilsCore -import FueledUtilsReactiveCommon -#endif @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Publisher where Output: TransferStateProtocol { @@ -35,5 +31,3 @@ extension Publisher where Output: TransferStateProtocol { .eraseToAnyPublisher() } } - -#endif diff --git a/FueledUtils/Combine/PublisherExtensions.swift b/Sources/FueledUtils/Combine/PublisherExtensions.swift similarity index 97% rename from FueledUtils/Combine/PublisherExtensions.swift rename to Sources/FueledUtils/Combine/PublisherExtensions.swift index dc2bb976..60421739 100644 --- a/FueledUtils/Combine/PublisherExtensions.swift +++ b/Sources/FueledUtils/Combine/PublisherExtensions.swift @@ -12,12 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) import Combine -#if canImport(FueledUtilsReactiveCommon) import FueledUtilsCore -import FueledUtilsReactiveCommon -#endif @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Publisher { @@ -109,5 +105,3 @@ extension Publisher where Output: OptionalProtocol { self.flatMap { ($0.wrapped.map { Just($0).eraseToAnyPublisher() } ?? Empty().eraseToAnyPublisher()).setFailureType(to: Failure.self) }.eraseToAnyPublisher() } } - -#endif diff --git a/FueledUtils/Combine/PublishersExtensions.swift b/Sources/FueledUtils/Combine/PublishersExtensions.swift similarity index 98% rename from FueledUtils/Combine/PublishersExtensions.swift rename to Sources/FueledUtils/Combine/PublishersExtensions.swift index d1126ce7..2d397034 100644 --- a/FueledUtils/Combine/PublishersExtensions.swift +++ b/Sources/FueledUtils/Combine/PublishersExtensions.swift @@ -12,12 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) import Combine -#if canImport(FueledUtilsReactiveCommon) import FueledUtilsCore -import FueledUtilsReactiveCommon -#endif @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Publishers { @@ -178,5 +174,3 @@ private final class CombineLatestManySubscription< self.$demandsState.modify { $0.cancel() } } } - -#endif diff --git a/FueledUtils/Combine/Subject+SendResult.swift b/Sources/FueledUtils/Combine/Subject+SendResult.swift similarity index 100% rename from FueledUtils/Combine/Subject+SendResult.swift rename to Sources/FueledUtils/Combine/Subject+SendResult.swift diff --git a/FueledUtils/Combine/Subscriber+EraseToAnySubscriber.swift b/Sources/FueledUtils/Combine/Subscriber+EraseToAnySubscriber.swift similarity index 100% rename from FueledUtils/Combine/Subscriber+EraseToAnySubscriber.swift rename to Sources/FueledUtils/Combine/Subscriber+EraseToAnySubscriber.swift diff --git a/FueledUtils/Core/AnyIdentifiable.swift b/Sources/FueledUtils/Core/AnyIdentifiable.swift similarity index 100% rename from FueledUtils/Core/AnyIdentifiable.swift rename to Sources/FueledUtils/Core/AnyIdentifiable.swift diff --git a/FueledUtils/Core/Atomic.swift b/Sources/FueledUtils/Core/Atomic.swift similarity index 100% rename from FueledUtils/Core/Atomic.swift rename to Sources/FueledUtils/Core/Atomic.swift diff --git a/FueledUtils/Core/CollectionExtensions.swift b/Sources/FueledUtils/Core/CollectionExtensions.swift similarity index 100% rename from FueledUtils/Core/CollectionExtensions.swift rename to Sources/FueledUtils/Core/CollectionExtensions.swift diff --git a/FueledUtils/Core/Lock.swift b/Sources/FueledUtils/Core/Lock.swift similarity index 100% rename from FueledUtils/Core/Lock.swift rename to Sources/FueledUtils/Core/Lock.swift diff --git a/FueledUtils/Core/NSDecimalNumberOperators.swift b/Sources/FueledUtils/Core/NSDecimalNumberOperators.swift similarity index 100% rename from FueledUtils/Core/NSDecimalNumberOperators.swift rename to Sources/FueledUtils/Core/NSDecimalNumberOperators.swift diff --git a/FueledUtils/Core/OptionalProtocol.swift b/Sources/FueledUtils/Core/OptionalProtocol.swift similarity index 100% rename from FueledUtils/Core/OptionalProtocol.swift rename to Sources/FueledUtils/Core/OptionalProtocol.swift diff --git a/FueledUtils/Core/OrderedSet.swift b/Sources/FueledUtils/Core/OrderedSet.swift similarity index 100% rename from FueledUtils/Core/OrderedSet.swift rename to Sources/FueledUtils/Core/OrderedSet.swift diff --git a/FueledUtils/Core/Regex.swift b/Sources/FueledUtils/Core/Regex.swift similarity index 100% rename from FueledUtils/Core/Regex.swift rename to Sources/FueledUtils/Core/Regex.swift diff --git a/FueledUtils/Core/SequenceExtensions.swift b/Sources/FueledUtils/Core/SequenceExtensions.swift similarity index 100% rename from FueledUtils/Core/SequenceExtensions.swift rename to Sources/FueledUtils/Core/SequenceExtensions.swift diff --git a/FueledUtils/Core/StringExtensions.swift b/Sources/FueledUtils/Core/StringExtensions.swift similarity index 100% rename from FueledUtils/Core/StringExtensions.swift rename to Sources/FueledUtils/Core/StringExtensions.swift diff --git a/FueledUtils/Core/SwiftExtensions.swift b/Sources/FueledUtils/Core/SwiftExtensions.swift similarity index 100% rename from FueledUtils/Core/SwiftExtensions.swift rename to Sources/FueledUtils/Core/SwiftExtensions.swift diff --git a/FueledUtils/Core/TransferState.swift b/Sources/FueledUtils/Core/TransferState.swift similarity index 100% rename from FueledUtils/Core/TransferState.swift rename to Sources/FueledUtils/Core/TransferState.swift diff --git a/FueledUtils/SwiftUI/BackgroundBlur.swift b/Sources/FueledUtils/SwiftUI/BackgroundBlur.swift similarity index 100% rename from FueledUtils/SwiftUI/BackgroundBlur.swift rename to Sources/FueledUtils/SwiftUI/BackgroundBlur.swift diff --git a/FueledUtils/SwiftUI/Binding+KeyPath.swift b/Sources/FueledUtils/SwiftUI/Binding+KeyPath.swift similarity index 100% rename from FueledUtils/SwiftUI/Binding+KeyPath.swift rename to Sources/FueledUtils/SwiftUI/Binding+KeyPath.swift diff --git a/FueledUtils/SwiftUI/BlurView.swift b/Sources/FueledUtils/SwiftUI/BlurView.swift similarity index 100% rename from FueledUtils/SwiftUI/BlurView.swift rename to Sources/FueledUtils/SwiftUI/BlurView.swift diff --git a/FueledUtils/SwiftUI/EdgeInsets+Helpers.swift b/Sources/FueledUtils/SwiftUI/EdgeInsets+Helpers.swift similarity index 100% rename from FueledUtils/SwiftUI/EdgeInsets+Helpers.swift rename to Sources/FueledUtils/SwiftUI/EdgeInsets+Helpers.swift diff --git a/FueledUtils/SwiftUI/ForEachWithIndex.swift b/Sources/FueledUtils/SwiftUI/ForEachWithIndex.swift similarity index 100% rename from FueledUtils/SwiftUI/ForEachWithIndex.swift rename to Sources/FueledUtils/SwiftUI/ForEachWithIndex.swift diff --git a/FueledUtils/SwiftUI/FramePreferenceKey.swift b/Sources/FueledUtils/SwiftUI/FramePreferenceKey.swift similarity index 100% rename from FueledUtils/SwiftUI/FramePreferenceKey.swift rename to Sources/FueledUtils/SwiftUI/FramePreferenceKey.swift diff --git a/FueledUtils/SwiftUI/View+AnyView.swift b/Sources/FueledUtils/SwiftUI/View+AnyView.swift similarity index 100% rename from FueledUtils/SwiftUI/View+AnyView.swift rename to Sources/FueledUtils/SwiftUI/View+AnyView.swift diff --git a/Tests/FueledUtils.xcodeproj/project.pbxproj b/Tests/FueledUtils.xcodeproj/project.pbxproj deleted file mode 100644 index f5c63e87..00000000 --- a/Tests/FueledUtils.xcodeproj/project.pbxproj +++ /dev/null @@ -1,433 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - EE9B3A498587AC2D3461D310 /* Pods_Common_FueledUtilsTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F46CDEA885028D8DB189B3CB /* Pods_Common_FueledUtilsTests.framework */; }; - F453AA7B2538DE55008F045B /* CombineLatestManySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453AA7A2538DE55008F045B /* CombineLatestManySpec.swift */; }; - F453AA802538E05E008F045B /* OrderedSetSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46D2DA5252E4E4A00B6987A /* OrderedSetSpec.swift */; }; - F453AA812538E05E008F045B /* CoalescingActionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = F499631F2537459200E2D4B5 /* CoalescingActionSpec.swift */; }; - F453AA822538E05E008F045B /* OverridingActionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = F429742D25378425004BFA85 /* OverridingActionSpec.swift */; }; - F453AA892538EF16008F045B /* SinkForLifetimeSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453AA882538EF16008F045B /* SinkForLifetimeSpec.swift */; }; - FC204075279EE4C9001A767C /* AnyCurrentValuePublisherSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC204074279EE4C9001A767C /* AnyCurrentValuePublisherSpec.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 00B6C3B54CADD6729AF81F36 /* Pods-Common-FueledUtilsTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-FueledUtilsTests.release.xcconfig"; path = "Target Support Files/Pods-Common-FueledUtilsTests/Pods-Common-FueledUtilsTests.release.xcconfig"; sourceTree = ""; }; - 1A3B52FAD952809D407DDA1E /* Pods_Common_asd_WatchKit_Extension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Common_asd_WatchKit_Extension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3297A6B2D4B923F8F27CD6A5 /* Pods-Common-FueledUtilsTests-SwiftUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-FueledUtilsTests-SwiftUI.release.xcconfig"; path = "Target Support Files/Pods-Common-FueledUtilsTests-SwiftUI/Pods-Common-FueledUtilsTests-SwiftUI.release.xcconfig"; sourceTree = ""; }; - 39EF9AE56A510B26CCC488B7 /* Pods_Common_FueledUtilsTests_SwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Common_FueledUtilsTests_SwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 48DE7B611288E2A6C99EEDAE /* Pods_Common_asd_WatchKit_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Common_asd_WatchKit_App.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A32E8FB94B9CE2642794723 /* Pods-Common-asd WatchKit Extension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-asd WatchKit Extension.release.xcconfig"; path = "Target Support Files/Pods-Common-asd WatchKit Extension/Pods-Common-asd WatchKit Extension.release.xcconfig"; sourceTree = ""; }; - 607FACE51AFB9204008FA782 /* FueledUtilsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FueledUtilsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 65B56BF0A7147538E12F737F /* Pods-Common-FueledUtilsTests-SwiftUI.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-FueledUtilsTests-SwiftUI.debug.xcconfig"; path = "Target Support Files/Pods-Common-FueledUtilsTests-SwiftUI/Pods-Common-FueledUtilsTests-SwiftUI.debug.xcconfig"; sourceTree = ""; }; - AB25EAABC0CDD547AE307879 /* Pods-Common-asd WatchKit App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-asd WatchKit App.release.xcconfig"; path = "Target Support Files/Pods-Common-asd WatchKit App/Pods-Common-asd WatchKit App.release.xcconfig"; sourceTree = ""; }; - ACF665E90E66C2B35C6C5C05 /* Pods-Common-FueledUtilsTests-ReactiveSwift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-FueledUtilsTests-ReactiveSwift.release.xcconfig"; path = "Target Support Files/Pods-Common-FueledUtilsTests-ReactiveSwift/Pods-Common-FueledUtilsTests-ReactiveSwift.release.xcconfig"; sourceTree = ""; }; - C783847C92189B0968E12A16 /* Pods-Common-asd WatchKit Extension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-asd WatchKit Extension.debug.xcconfig"; path = "Target Support Files/Pods-Common-asd WatchKit Extension/Pods-Common-asd WatchKit Extension.debug.xcconfig"; sourceTree = ""; }; - CF40A2CC4151F8E9B373D243 /* FueledUtils.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = FueledUtils.podspec; path = ../FueledUtils.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - D43FD9799A872E88963939C1 /* Pods-Common-FueledUtilsTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-FueledUtilsTests.debug.xcconfig"; path = "Target Support Files/Pods-Common-FueledUtilsTests/Pods-Common-FueledUtilsTests.debug.xcconfig"; sourceTree = ""; }; - D498AEE5BC8A0A514416E6DA /* Pods-Common-FueledUtilsTests-ReactiveSwift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-FueledUtilsTests-ReactiveSwift.debug.xcconfig"; path = "Target Support Files/Pods-Common-FueledUtilsTests-ReactiveSwift/Pods-Common-FueledUtilsTests-ReactiveSwift.debug.xcconfig"; sourceTree = ""; }; - E7AC5BA00D7F6054AC66E468 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; - E82CDABCC774F7F31D52705D /* Pods-Common-asd WatchKit App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Common-asd WatchKit App.debug.xcconfig"; path = "Target Support Files/Pods-Common-asd WatchKit App/Pods-Common-asd WatchKit App.debug.xcconfig"; sourceTree = ""; }; - F429742D25378425004BFA85 /* OverridingActionSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverridingActionSpec.swift; sourceTree = ""; }; - F453AA7A2538DE55008F045B /* CombineLatestManySpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineLatestManySpec.swift; sourceTree = ""; }; - F453AA882538EF16008F045B /* SinkForLifetimeSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SinkForLifetimeSpec.swift; sourceTree = ""; }; - F463C73F241835EA000A0B29 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - F46CDEA885028D8DB189B3CB /* Pods_Common_FueledUtilsTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Common_FueledUtilsTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - F46D2DA5252E4E4A00B6987A /* OrderedSetSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSetSpec.swift; sourceTree = ""; }; - F499631F2537459200E2D4B5 /* CoalescingActionSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoalescingActionSpec.swift; sourceTree = ""; }; - F7F10FE9C8384333882C2368 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; - FC204074279EE4C9001A767C /* AnyCurrentValuePublisherSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyCurrentValuePublisherSpec.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 607FACE21AFB9204008FA782 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EE9B3A498587AC2D3461D310 /* Pods_Common_FueledUtilsTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 29F7E676D0DA9F23C4893ECA /* Pods */ = { - isa = PBXGroup; - children = ( - D498AEE5BC8A0A514416E6DA /* Pods-Common-FueledUtilsTests-ReactiveSwift.debug.xcconfig */, - ACF665E90E66C2B35C6C5C05 /* Pods-Common-FueledUtilsTests-ReactiveSwift.release.xcconfig */, - 65B56BF0A7147538E12F737F /* Pods-Common-FueledUtilsTests-SwiftUI.debug.xcconfig */, - 3297A6B2D4B923F8F27CD6A5 /* Pods-Common-FueledUtilsTests-SwiftUI.release.xcconfig */, - D43FD9799A872E88963939C1 /* Pods-Common-FueledUtilsTests.debug.xcconfig */, - 00B6C3B54CADD6729AF81F36 /* Pods-Common-FueledUtilsTests.release.xcconfig */, - C783847C92189B0968E12A16 /* Pods-Common-asd WatchKit Extension.debug.xcconfig */, - 4A32E8FB94B9CE2642794723 /* Pods-Common-asd WatchKit Extension.release.xcconfig */, - E82CDABCC774F7F31D52705D /* Pods-Common-asd WatchKit App.debug.xcconfig */, - AB25EAABC0CDD547AE307879 /* Pods-Common-asd WatchKit App.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - 607FACC71AFB9204008FA782 = { - isa = PBXGroup; - children = ( - 607FACF51AFB993E008FA782 /* Podspec Metadata */, - F463C739241835DD000A0B29 /* Tests */, - F463C73E241835EA000A0B29 /* Supporting Files */, - 607FACD11AFB9204008FA782 /* Products */, - 29F7E676D0DA9F23C4893ECA /* Pods */, - 8CF3F11B25F743ED68711CBC /* Frameworks */, - ); - sourceTree = ""; - }; - 607FACD11AFB9204008FA782 /* Products */ = { - isa = PBXGroup; - children = ( - 607FACE51AFB9204008FA782 /* FueledUtilsTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { - isa = PBXGroup; - children = ( - CF40A2CC4151F8E9B373D243 /* FueledUtils.podspec */, - E7AC5BA00D7F6054AC66E468 /* README.md */, - F7F10FE9C8384333882C2368 /* LICENSE */, - ); - name = "Podspec Metadata"; - sourceTree = ""; - }; - 8CF3F11B25F743ED68711CBC /* Frameworks */ = { - isa = PBXGroup; - children = ( - 39EF9AE56A510B26CCC488B7 /* Pods_Common_FueledUtilsTests_SwiftUI.framework */, - F46CDEA885028D8DB189B3CB /* Pods_Common_FueledUtilsTests.framework */, - 1A3B52FAD952809D407DDA1E /* Pods_Common_asd_WatchKit_Extension.framework */, - 48DE7B611288E2A6C99EEDAE /* Pods_Common_asd_WatchKit_App.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - F463C739241835DD000A0B29 /* Tests */ = { - isa = PBXGroup; - children = ( - FC204074279EE4C9001A767C /* AnyCurrentValuePublisherSpec.swift */, - F499631F2537459200E2D4B5 /* CoalescingActionSpec.swift */, - F46D2DA5252E4E4A00B6987A /* OrderedSetSpec.swift */, - F429742D25378425004BFA85 /* OverridingActionSpec.swift */, - F453AA7A2538DE55008F045B /* CombineLatestManySpec.swift */, - F453AA882538EF16008F045B /* SinkForLifetimeSpec.swift */, - ); - path = Tests; - sourceTree = ""; - }; - F463C73E241835EA000A0B29 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - F463C73F241835EA000A0B29 /* Info.plist */, - ); - path = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 607FACE41AFB9204008FA782 /* FueledUtilsTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "FueledUtilsTests" */; - buildPhases = ( - 7A704080E54E9F7FB6D2806D /* [CP] Check Pods Manifest.lock */, - 607FACE11AFB9204008FA782 /* Sources */, - 607FACE21AFB9204008FA782 /* Frameworks */, - 607FACE31AFB9204008FA782 /* Resources */, - 41CB9636F71B84882C2E6A45 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = FueledUtilsTests; - productName = Tests; - productReference = 607FACE51AFB9204008FA782 /* FueledUtilsTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 607FACC81AFB9204008FA782 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1200; - LastUpgradeCheck = 1140; - ORGANIZATIONNAME = CocoaPods; - TargetAttributes = { - 607FACE41AFB9204008FA782 = { - CreatedOnToolsVersion = 6.3.1; - LastSwiftMigration = 0900; - }; - }; - }; - buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "FueledUtils" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 607FACC71AFB9204008FA782; - productRefGroup = 607FACD11AFB9204008FA782 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 607FACE41AFB9204008FA782 /* FueledUtilsTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 607FACE31AFB9204008FA782 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 41CB9636F71B84882C2E6A45 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Common-FueledUtilsTests/Pods-Common-FueledUtilsTests-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/FueledUtils/FueledUtils.framework", - "${BUILT_PRODUCTS_DIR}/Nimble/Nimble.framework", - "${BUILT_PRODUCTS_DIR}/Quick/Quick.framework", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FueledUtils.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Quick.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Common-FueledUtilsTests/Pods-Common-FueledUtilsTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 7A704080E54E9F7FB6D2806D /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Common-FueledUtilsTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 607FACE11AFB9204008FA782 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - F453AA7B2538DE55008F045B /* CombineLatestManySpec.swift in Sources */, - F453AA802538E05E008F045B /* OrderedSetSpec.swift in Sources */, - FC204075279EE4C9001A767C /* AnyCurrentValuePublisherSpec.swift in Sources */, - F453AA892538EF16008F045B /* SinkForLifetimeSpec.swift in Sources */, - F453AA822538E05E008F045B /* OverridingActionSpec.swift in Sources */, - F453AA812538E05E008F045B /* CoalescingActionSpec.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 607FACED1AFB9204008FA782 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 607FACEE1AFB9204008FA782 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 607FACF31AFB9204008FA782 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D43FD9799A872E88963939C1 /* Pods-Common-FueledUtilsTests.debug.xcconfig */; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = "Supporting Files/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.fueled.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 607FACF41AFB9204008FA782 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 00B6C3B54CADD6729AF81F36 /* Pods-Common-FueledUtilsTests.release.xcconfig */; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = "Supporting Files/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.fueled.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "FueledUtils" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 607FACED1AFB9204008FA782 /* Debug */, - 607FACEE1AFB9204008FA782 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "FueledUtilsTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 607FACF31AFB9204008FA782 /* Debug */, - 607FACF41AFB9204008FA782 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 607FACC81AFB9204008FA782 /* Project object */; -} diff --git a/Tests/FueledUtils.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Tests/FueledUtils.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 8fe1237a..00000000 --- a/Tests/FueledUtils.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Tests/FueledUtils.xcodeproj/xcshareddata/xcschemes/FueledUtils/ReactiveSwift.xcscheme b/Tests/FueledUtils.xcodeproj/xcshareddata/xcschemes/FueledUtils/ReactiveSwift.xcscheme deleted file mode 100644 index cc6ad7ff..00000000 --- a/Tests/FueledUtils.xcodeproj/xcshareddata/xcschemes/FueledUtils/ReactiveSwift.xcscheme +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tests/FueledUtils.xcodeproj/xcshareddata/xcschemes/FueledUtilsTests.xcscheme b/Tests/FueledUtils.xcodeproj/xcshareddata/xcschemes/FueledUtilsTests.xcscheme deleted file mode 100644 index f2a5dc09..00000000 --- a/Tests/FueledUtils.xcodeproj/xcshareddata/xcschemes/FueledUtilsTests.xcscheme +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tests/FueledUtils.xcworkspace/contents.xcworkspacedata b/Tests/FueledUtils.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 514f9518..00000000 --- a/Tests/FueledUtils.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/Tests/FueledUtils.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Tests/FueledUtils.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/Tests/FueledUtils.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Tests/Tests/AnyCurrentValuePublisherSpec.swift b/Tests/FueledUtils/CombineTests/AnyCurrentValuePublisherSpec.swift similarity index 87% rename from Tests/Tests/AnyCurrentValuePublisherSpec.swift rename to Tests/FueledUtils/CombineTests/AnyCurrentValuePublisherSpec.swift index 695fab22..15cd8212 100644 --- a/Tests/Tests/AnyCurrentValuePublisherSpec.swift +++ b/Tests/FueledUtils/CombineTests/AnyCurrentValuePublisherSpec.swift @@ -12,14 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) +@testable import FueledUtilsCombine + import Combine -#if canImport(FueledUtilsCombine) -import FueledUtilsCombine -#elseif canImport(FueledUtils) -import FueledUtils -#endif -import Foundation import Quick import Nimble @@ -40,4 +35,3 @@ class AnyCurrentValuePublisherSpec: QuickSpec { } } } -#endif diff --git a/Tests/Tests/CoalescingActionSpec.swift b/Tests/FueledUtils/CombineTests/CoalescingActionSpec.swift similarity index 91% rename from Tests/Tests/CoalescingActionSpec.swift rename to Tests/FueledUtils/CombineTests/CoalescingActionSpec.swift index d8d5f27d..65b5fb15 100644 --- a/Tests/Tests/CoalescingActionSpec.swift +++ b/Tests/FueledUtils/CombineTests/CoalescingActionSpec.swift @@ -12,13 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) +@testable import FueledUtilsCombine + import Combine -#if canImport(FueledUtilsCombine) -import FueledUtilsCombine -#elseif canImport(FueledUtils) -import FueledUtils -#endif import Foundation import Quick import Nimble @@ -62,5 +58,3 @@ class CoalescingActionSpec: QuickSpec { } } } - -#endif diff --git a/Tests/Tests/CombineLatestManySpec.swift b/Tests/FueledUtils/CombineTests/CombineLatestManySpec.swift similarity index 97% rename from Tests/Tests/CombineLatestManySpec.swift rename to Tests/FueledUtils/CombineTests/CombineLatestManySpec.swift index 5005e1d4..8dcc1bd8 100644 --- a/Tests/Tests/CombineLatestManySpec.swift +++ b/Tests/FueledUtils/CombineTests/CombineLatestManySpec.swift @@ -12,13 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) +@testable import FueledUtilsCombine + import Combine -#if canImport(FueledUtilsCombine) -import FueledUtilsCombine -#elseif canImport(FueledUtils) -import FueledUtils -#endif import Foundation import Quick import Nimble @@ -196,5 +192,3 @@ class CombineLatestManySpec: QuickSpec { } } } - -#endif diff --git a/Tests/Tests/OverridingActionSpec.swift b/Tests/FueledUtils/CombineTests/OverridingActionSpec.swift similarity index 92% rename from Tests/Tests/OverridingActionSpec.swift rename to Tests/FueledUtils/CombineTests/OverridingActionSpec.swift index 0e8f5205..422e2d4b 100644 --- a/Tests/Tests/OverridingActionSpec.swift +++ b/Tests/FueledUtils/CombineTests/OverridingActionSpec.swift @@ -12,13 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if canImport(Combine) +@testable import FueledUtilsCombine import Combine -#if canImport(FueledUtilsCombine) -import FueledUtilsCombine -#elseif canImport(FueledUtils) -import FueledUtils -#endif import Foundation import Quick import Nimble @@ -68,5 +63,3 @@ class OverridingActionSpec: QuickSpec { } } } - -#endif diff --git a/Tests/Tests/SinkForLifetimeSpec.swift b/Tests/FueledUtils/CombineTests/SinkForLifetimeSpec.swift similarity index 90% rename from Tests/Tests/SinkForLifetimeSpec.swift rename to Tests/FueledUtils/CombineTests/SinkForLifetimeSpec.swift index 402c44fa..edab0ba1 100644 --- a/Tests/Tests/SinkForLifetimeSpec.swift +++ b/Tests/FueledUtils/CombineTests/SinkForLifetimeSpec.swift @@ -12,16 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +@testable import FueledUtilsCombine + +import Combine +import Foundation import Quick import Nimble -#if canImport(FueledUtilsCombine) -import FueledUtilsCombine -#elseif canImport(FueledUtils) -import FueledUtils -#endif -import Foundation -#if canImport(Combine) -import Combine class SinkForLifetimeSpec: QuickSpec { override func spec() { @@ -54,5 +50,3 @@ class SinkForLifetimeSpec: QuickSpec { } } } - -#endif diff --git a/Tests/Tests/OrderedSetSpec.swift b/Tests/FueledUtils/CoreTests/OrderedSetSpec.swift similarity index 94% rename from Tests/Tests/OrderedSetSpec.swift rename to Tests/FueledUtils/CoreTests/OrderedSetSpec.swift index b5b2ad41..273f663e 100644 --- a/Tests/Tests/OrderedSetSpec.swift +++ b/Tests/FueledUtils/CoreTests/OrderedSetSpec.swift @@ -12,13 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +@testable import FueledUtilsCore + import Quick import Nimble -#if canImport(FueledUtilsCore) -import FueledUtilsCore -#elseif canImport(FueledUtils) -import FueledUtils -#endif import XCTest class OrderedSetSpec: QuickSpec { diff --git a/Tests/Podfile b/Tests/Podfile deleted file mode 100644 index 01aa80d2..00000000 --- a/Tests/Podfile +++ /dev/null @@ -1,14 +0,0 @@ -use_frameworks! - -abstract_target 'Common' do - target 'FueledUtilsTests' do - platform :ios, '13.0' - - pod 'Quick', '~> 2.0' - pod 'Nimble', '~> 9.0' - - pod 'FueledUtils/SwiftUI', path: '../' - pod 'FueledUtils/CombineOperators', path: '../' - pod 'FueledUtils/CombineUIKit', path: '../' - end -end diff --git a/Tests/Podfile.lock b/Tests/Podfile.lock deleted file mode 100644 index 7da674d5..00000000 --- a/Tests/Podfile.lock +++ /dev/null @@ -1,43 +0,0 @@ -PODS: - - FueledUtils/Combine (3.1.0): - - FueledUtils/ReactiveCommon - - FueledUtils/CombineOperators (3.1.0): - - FueledUtils/Combine - - FueledUtils/CombineUIKit (3.1.0): - - FueledUtils/Combine - - FueledUtils/UIKit - - FueledUtils/Core (3.1.0) - - FueledUtils/ReactiveCommon (3.1.0): - - FueledUtils/Core - - FueledUtils/SwiftUI (3.1.0): - - FueledUtils/Combine - - FueledUtils/Core - - FueledUtils/UIKit (3.1.0): - - FueledUtils/Core - - Nimble (9.2.1) - - Quick (2.2.1) - -DEPENDENCIES: - - FueledUtils/CombineOperators (from `../`) - - FueledUtils/CombineUIKit (from `../`) - - FueledUtils/SwiftUI (from `../`) - - Nimble (~> 9.0) - - Quick (~> 2.0) - -SPEC REPOS: - trunk: - - Nimble - - Quick - -EXTERNAL SOURCES: - FueledUtils: - :path: "../" - -SPEC CHECKSUMS: - FueledUtils: bbda6596f2628c440573f999ae8cbbaf9c473867 - Nimble: e7e615c0335ee4bf5b0d786685451e62746117d5 - Quick: f5754d69b7013f5864c29aab9ae6f0c79c5bc200 - -PODFILE CHECKSUM: 5e7730fbfc9f6b43738b7d63954e9efd24986406 - -COCOAPODS: 1.11.2 diff --git a/Tests/Supporting Files/Info.plist b/Tests/Supporting Files/Info.plist deleted file mode 100644 index 6c40a6cd..00000000 --- a/Tests/Supporting Files/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/_Pods.xcodeproj b/_Pods.xcodeproj deleted file mode 120000 index 3c5a8e71..00000000 --- a/_Pods.xcodeproj +++ /dev/null @@ -1 +0,0 @@ -Example/Pods/Pods.xcodeproj \ No newline at end of file