From 00eb5601b755eb0e7fae896fdf71933b301bf4e4 Mon Sep 17 00:00:00 2001 From: Michael Wagner Date: Thu, 27 Dec 2018 14:35:25 +0100 Subject: [PATCH 1/7] feat: Add foregroundViewStore to bring some subviews for specific states to the front --- Example.xcodeproj/project.pbxproj | 7 + Example/Base.lproj/Main.storyboard | 147 ++++++++++++++++-- .../ForegroundViewStoreViewController.swift | 128 +++++++++++++++ Example/ViewController.swift | 4 +- .../StatefulViewController.swift | 4 +- ...StatefulViewControllerImplementation.swift | 14 +- StatefulViewController/ViewStateMachine.swift | 29 ++++ 7 files changed, 314 insertions(+), 19 deletions(-) create mode 100644 Example/ForegroundViewStoreViewController.swift diff --git a/Example.xcodeproj/project.pbxproj b/Example.xcodeproj/project.pbxproj index 82e57ca..82e329c 100644 --- a/Example.xcodeproj/project.pbxproj +++ b/Example.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 523646911C6F88CF00392180 /* StatefulViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6451661A64089800108EA3 /* StatefulViewController.swift */; }; 523646921C6F88CF00392180 /* StatefulViewControllerImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC230DC1BB5BA810083B95A /* StatefulViewControllerImplementation.swift */; }; 523646931C6F88CF00392180 /* ViewStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6451671A64089800108EA3 /* ViewStateMachine.swift */; }; + D377D48A21D5018800C93544 /* ForegroundViewStoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D377D48921D5018800C93544 /* ForegroundViewStoreViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -97,6 +98,7 @@ 4DE62B0B19B65AF00021630A /* ErrorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = ""; }; 4DE62B0C19B65AF00021630A /* LoadingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; 523646881C6F87B000392180 /* StatefulViewController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StatefulViewController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D377D48921D5018800C93544 /* ForegroundViewStoreViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForegroundViewStoreViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -199,6 +201,7 @@ 4DE62AE319B658610021630A /* ViewController.swift */, 4D0EA4711ECAF83E00139926 /* TableViewController.swift */, 4D0EA4731ECB052000139926 /* CollectionViewController.swift */, + D377D48921D5018800C93544 /* ForegroundViewStoreViewController.swift */, 4DE62B0819B65AF00021630A /* PlaceholderViews */, 4DE62AE519B658610021630A /* Main.storyboard */, 4D137EB619C1BE5700AC1050 /* LaunchScreen.xib */, @@ -345,6 +348,7 @@ }; 4DE62ADB19B658610021630A = { CreatedOnToolsVersion = 6.0; + DevelopmentTeam = T3TBY9W4TM; LastSwiftMigration = 1000; }; 523646871C6F87B000392180 = { @@ -434,6 +438,7 @@ 4DE62AE419B658610021630A /* ViewController.swift in Sources */, 4D0EA4721ECAF83E00139926 /* TableViewController.swift in Sources */, 4DE62B0D19B65AF00021630A /* BasicPlaceholderView.swift in Sources */, + D377D48A21D5018800C93544 /* ForegroundViewStoreViewController.swift in Sources */, 4DE62AE219B658610021630A /* AppDelegate.swift in Sources */, 4D0EA4741ECB052000139926 /* CollectionViewController.swift in Sources */, 4DE62B0F19B65AF00021630A /* ErrorView.swift in Sources */, @@ -687,6 +692,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = T3TBY9W4TM; INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.aschuch.$(PRODUCT_NAME:rfc1034identifier)"; @@ -699,6 +705,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = T3TBY9W4TM; INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.aschuch.$(PRODUCT_NAME:rfc1034identifier)"; diff --git a/Example/Base.lproj/Main.storyboard b/Example/Base.lproj/Main.storyboard index 1a6c661..e691035 100644 --- a/Example/Base.lproj/Main.storyboard +++ b/Example/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - - + + - + @@ -29,11 +29,11 @@ - + diff --git a/Example/ForegroundViewStoreViewController.swift b/Example/ForegroundViewStoreViewController.swift new file mode 100644 index 0000000..2aee319 --- /dev/null +++ b/Example/ForegroundViewStoreViewController.swift @@ -0,0 +1,128 @@ +// +// ForegroundViewStoreViewController.swift +// Example +// +// Created by Matthias Wagner on 27.12.18. +// Copyright © 2018 Alexander Schuch. All rights reserved. +// + +import UIKit +import StatefulViewController + +class ForegroundViewStoreViewController: UIViewController, StatefulViewController { + + // MARK: - IBOutlets + + @IBOutlet weak var tableView: UITableView! + + @IBOutlet weak var deleteButton: UIButton! + + @IBOutlet weak var addButton: UIButton! + + // MARK: - Properties + + private let refreshControl = UIRefreshControl() + + fileprivate var dataArray = [String]() + + // MARK: - LifeCylce + + override func viewDidLoad() { + super.viewDidLoad() + + // Setup refresh control + refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged) + tableView.addSubview(refreshControl) + + // Setup placeholder views + loadingView = LoadingView(frame: view.frame) + emptyView = EmptyView(frame: view.frame) + let failureView = ErrorView(frame: view.frame) + failureView.tapGestureRecognizer.addTarget(self, action: #selector(refresh)) + errorView = failureView + + foregroundViewStore = [StatefulViewControllerState.empty: [addButton]] + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + setupInitialViewState() + refresh() + } + + // MARK: - Refresh + + @objc func refresh() { + if (lastState == .loading) { return } + + startLoading { + print("completaion startLoading -> loadingState: \(self.currentState.rawValue)") + } + print("startLoading -> loadingState: \(self.lastState.rawValue)") + + // Fake network call + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(3 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { + + // Success + self.dataArray = ["Merlot", "Sauvignon Blanc", "Blaufränkisch", "Pinot Nior"] + self.tableView.reloadData() + self.endLoading(error: nil, completion: { + print("completion endLoading -> loadingState: \(self.currentState.rawValue)") + }) + print("endLoading -> loadingState: \(self.lastState.rawValue)") + + // Error + //self.endLoading(error: NSError(domain: "foo", code: -1, userInfo: nil)) + + // No Content + //self.endLoading(error: nil) + + self.refreshControl.endRefreshing() + } + } + + // MARK: - IBActions + + @IBAction func onRefresh(_ sender: Any) { + refresh() + } + + @IBAction func onDeleteButton(_ sender: Any) { + foregroundViewStore?[StatefulViewControllerState.empty]?.remove(deleteButton) + } + + @IBAction func onAddButton(_ sender: Any) { + foregroundViewStore?[StatefulViewControllerState.empty]?.insert(deleteButton) + } +} + + +extension ForegroundViewStoreViewController { + + func hasContent() -> Bool { + return false + } + + func handleErrorWhenContentAvailable(_ error: Error) { + let alertController = UIAlertController(title: "Ooops", message: "Something went wrong.", preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + self.present(alertController, animated: true, completion: nil) + } + +} + +// MARK: - UITableViewDataSource + +extension ForegroundViewStoreViewController: UITableViewDataSource { + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return dataArray.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "textCell", for: indexPath) + cell.textLabel?.text = dataArray[(indexPath as NSIndexPath).row] + return cell + } +} diff --git a/Example/ViewController.swift b/Example/ViewController.swift index 4bd7f74..2e11d39 100644 --- a/Example/ViewController.swift +++ b/Example/ViewController.swift @@ -13,6 +13,8 @@ class ViewController: UIViewController, StatefulViewController { fileprivate var dataArray = [String]() private let refreshControl = UIRefreshControl() @IBOutlet weak var tableView: UITableView! + + var foregroundViewStore = [StatefulViewControllerState.empty: []] override func viewDidLoad() { super.viewDidLoad() @@ -31,7 +33,7 @@ class ViewController: UIViewController, StatefulViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - + setupInitialViewState() refresh() } diff --git a/StatefulViewController/StatefulViewController.swift b/StatefulViewController/StatefulViewController.swift index ea43248..90149b9 100644 --- a/StatefulViewController/StatefulViewController.swift +++ b/StatefulViewController/StatefulViewController.swift @@ -42,7 +42,9 @@ public protocol StatefulViewController: class, BackingViewProvider { /// The empty view is shown when the `hasContent` method returns false var emptyView: UIView? { get set } - + /// This store includes the views, who should be in the front during the specific state (Key) + var foregroundViewStore: [StatefulViewControllerState: Set]? { get set } + // MARK: Transitions /// Sets up the initial state of the view. diff --git a/StatefulViewController/StatefulViewControllerImplementation.swift b/StatefulViewController/StatefulViewControllerImplementation.swift index 26b9b27..4c99b11 100644 --- a/StatefulViewController/StatefulViewControllerImplementation.swift +++ b/StatefulViewController/StatefulViewControllerImplementation.swift @@ -58,7 +58,11 @@ extension StatefulViewController { get { return placeholderView(.empty) } set { setPlaceholderView(newValue, forState: .empty) } } - + + public var foregroundViewStore: [StatefulViewControllerState: Set]? { + get { return getForegroundStore() } + set { setForegroundViewStore(newValue) } + } // MARK: Transitions @@ -118,6 +122,14 @@ extension StatefulViewController { fileprivate func setPlaceholderView(_ view: UIView?, forState state: StatefulViewControllerState) { stateMachine[state.rawValue] = view } + + fileprivate func getForegroundStore() -> [StatefulViewControllerState: Set]? { + return stateMachine.foregroundViewStore + } + + fileprivate func setForegroundViewStore(_ store: [StatefulViewControllerState: Set]?) { + stateMachine.foregroundViewStore = store + } } diff --git a/StatefulViewController/ViewStateMachine.swift b/StatefulViewController/ViewStateMachine.swift index cd1dca9..5cd51cf 100644 --- a/StatefulViewController/ViewStateMachine.swift +++ b/StatefulViewController/ViewStateMachine.swift @@ -53,6 +53,27 @@ public class ViewStateMachine { /// The view that should act as the superview for any added views public let view: UIView + + /// This store includes the views, who should be in the front during the specific state (Key) + public var foregroundViewStore: [StatefulViewControllerState: Set]? = nil { + didSet { + view.bringSubviewToFront(containerView) // Reset to the default order + + if let foregroundViewStore = foregroundViewStore { + switch currentState { + case .none: break + case .view(let stateKey): + + // Bring all stored views for the state to the front + if let state = StatefulViewControllerState(rawValue: stateKey), let foregroundViews = foregroundViewStore[state] { + for foregroundView in foregroundViews { + view.bringSubviewToFront(foregroundView) + } + } + } + } + } + } /// The current display state of views public fileprivate(set) var currentState: ViewStateMachineState = .none @@ -184,6 +205,14 @@ public class ViewStateMachine { containerView.addConstraints(vConstraints) } + // Bring all views from the foregroundViewStore, stored for the specific state, to the front + if let state = StatefulViewControllerState(rawValue: state), let foregroundViewStore = foregroundViewStore, let foregroundViews = foregroundViewStore[state] { + + for foregroundView in foregroundViews { + view.bringSubviewToFront(foregroundView) + } + } + let animations: () -> () = { if let newView = store[state] { newView.alpha = 1.0 From 763c1375fb28398088fd3025138a61336d76adf8 Mon Sep 17 00:00:00 2001 From: Michael Wagner Date: Thu, 27 Dec 2018 17:54:34 +0100 Subject: [PATCH 2/7] refactor: Use shorter keys in the example dicts --- Example/ForegroundViewStoreViewController.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Example/ForegroundViewStoreViewController.swift b/Example/ForegroundViewStoreViewController.swift index 2aee319..cfaa186 100644 --- a/Example/ForegroundViewStoreViewController.swift +++ b/Example/ForegroundViewStoreViewController.swift @@ -41,7 +41,10 @@ class ForegroundViewStoreViewController: UIViewController, StatefulViewControlle failureView.tapGestureRecognizer.addTarget(self, action: #selector(refresh)) errorView = failureView - foregroundViewStore = [StatefulViewControllerState.empty: [addButton]] + foregroundViewStore = [ + .empty: [addButton], + .error: [addButton] + ] } override func viewWillAppear(_ animated: Bool) { @@ -89,11 +92,11 @@ class ForegroundViewStoreViewController: UIViewController, StatefulViewControlle } @IBAction func onDeleteButton(_ sender: Any) { - foregroundViewStore?[StatefulViewControllerState.empty]?.remove(deleteButton) + foregroundViewStore?[.empty]?.remove(deleteButton) } @IBAction func onAddButton(_ sender: Any) { - foregroundViewStore?[StatefulViewControllerState.empty]?.insert(deleteButton) + foregroundViewStore?[.empty]?.insert(deleteButton) } } From 86c0ba52ff4ea793c00080af072b0f1e0451cade Mon Sep 17 00:00:00 2001 From: Michael Wagner Date: Thu, 27 Dec 2018 17:56:00 +0100 Subject: [PATCH 3/7] chore: Update Readme - add usage description for the foregroundViewStore --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index f178392..48a11d9 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,25 @@ class MyPlaceholderView: UIView, StatefulPlaceholderView { +### ForegroundViewStore + +Per default, StatefulViewController presents the placeholder views above all other views. In case other views, like some buttons, should be above the placholder in some states, you can assign a dictionary `[StatefulViewControllerState: Set]` to the `foregroundViewStore` property. + +```swift +foregroundViewStore = [ + .empty: [button1, button2], + .error: [button1] +] +``` + +You can also update the `foregroundViewStore` later: + +```swift +foregroundViewStore?[.empty]?.remove(button1) +foregroundViewStore?[.loading]?.insert(button3) +``` + + ### View State Machine From a1de0af6fd277cd68b592608416286911a5730a6 Mon Sep 17 00:00:00 2001 From: Matthias Buchetics Date: Mon, 1 Apr 2019 10:05:40 +0200 Subject: [PATCH 4/7] updated for Swift 5 --- Example.xcodeproj/project.pbxproj | 45 ++++++++++--------- .../StatefulViewController-iOS Tests.xcscheme | 11 ++++- .../StatefulViewController-iOS.xcscheme | 2 +- .../StatefulViewController-tvOS.xcscheme | 2 +- LICENSE | 1 + README.md | 15 ++----- 6 files changed, 41 insertions(+), 35 deletions(-) diff --git a/Example.xcodeproj/project.pbxproj b/Example.xcodeproj/project.pbxproj index 82e329c..1453d71 100644 --- a/Example.xcodeproj/project.pbxproj +++ b/Example.xcodeproj/project.pbxproj @@ -334,22 +334,23 @@ attributes = { LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 1000; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = "Alexander Schuch"; TargetAttributes = { 4D6451451A64079200108EA3 = { CreatedOnToolsVersion = 6.2; - LastSwiftMigration = 1000; + LastSwiftMigration = 1020; }; 4D64514F1A64079200108EA3 = { CreatedOnToolsVersion = 6.2; - LastSwiftMigration = 1000; + DevelopmentTeam = M8F9QH57A6; + LastSwiftMigration = 1020; TestTargetID = 4DE62ADB19B658610021630A; }; 4DE62ADB19B658610021630A = { CreatedOnToolsVersion = 6.0; - DevelopmentTeam = T3TBY9W4TM; - LastSwiftMigration = 1000; + DevelopmentTeam = M8F9QH57A6; + LastSwiftMigration = 1020; }; 523646871C6F87B000392180 = { CreatedOnToolsVersion = 7.2.1; @@ -358,7 +359,7 @@ }; buildConfigurationList = 4DE62AD719B658610021630A /* Build configuration list for PBXProject "Example" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -516,11 +517,11 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.aschuch.StatefulViewController; + PRODUCT_BUNDLE_IDENTIFIER = at.allaboutapps.StatefulViewController; PRODUCT_NAME = StatefulViewController; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -542,10 +543,10 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.aschuch.StatefulViewController; + PRODUCT_BUNDLE_IDENTIFIER = at.allaboutapps.StatefulViewController; PRODUCT_NAME = StatefulViewController; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -555,6 +556,7 @@ 4D6451611A64079300108EA3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + DEVELOPMENT_TEAM = M8F9QH57A6; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -565,7 +567,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.aschuch.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; }; name = Debug; @@ -574,13 +576,14 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = M8F9QH57A6; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = StatefulViewControllerTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.aschuch.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; }; name = Release; @@ -589,6 +592,7 @@ 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; @@ -644,6 +648,7 @@ 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; @@ -692,12 +697,12 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - DEVELOPMENT_TEAM = T3TBY9W4TM; + DEVELOPMENT_TEAM = M8F9QH57A6; INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.aschuch.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = at.allaboutapps.StatefulViewControllerExample; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -705,12 +710,12 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - DEVELOPMENT_TEAM = T3TBY9W4TM; + DEVELOPMENT_TEAM = M8F9QH57A6; INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.aschuch.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = at.allaboutapps.StatefulViewControllerExample; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -728,7 +733,7 @@ INFOPLIST_FILE = "$(SRCROOT)/StatefulViewController/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.aschuch.StatefulViewController; + PRODUCT_BUNDLE_IDENTIFIER = at.allaboutapps.StatefulViewController; PRODUCT_NAME = StatefulViewController; SDKROOT = appletvos; SKIP_INSTALL = YES; @@ -754,7 +759,7 @@ INFOPLIST_FILE = "$(SRCROOT)/StatefulViewController/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.aschuch.StatefulViewController; + PRODUCT_BUNDLE_IDENTIFIER = at.allaboutapps.StatefulViewController; PRODUCT_NAME = StatefulViewController; SDKROOT = appletvos; SKIP_INSTALL = YES; diff --git a/Example.xcodeproj/xcshareddata/xcschemes/StatefulViewController-iOS Tests.xcscheme b/Example.xcodeproj/xcshareddata/xcschemes/StatefulViewController-iOS Tests.xcscheme index 6122baa..78ba3e7 100644 --- a/Example.xcodeproj/xcshareddata/xcschemes/StatefulViewController-iOS Tests.xcscheme +++ b/Example.xcodeproj/xcshareddata/xcschemes/StatefulViewController-iOS Tests.xcscheme @@ -1,6 +1,6 @@ + + + + diff --git a/Example.xcodeproj/xcshareddata/xcschemes/StatefulViewController-iOS.xcscheme b/Example.xcodeproj/xcshareddata/xcschemes/StatefulViewController-iOS.xcscheme index 1ae15de..20d1d39 100644 --- a/Example.xcodeproj/xcshareddata/xcschemes/StatefulViewController-iOS.xcscheme +++ b/Example.xcodeproj/xcshareddata/xcschemes/StatefulViewController-iOS.xcscheme @@ -1,6 +1,6 @@ 3.0 +github "aschuch/StatefulViewController" ~> 5.0 ``` Then run `carthage update`. -#### CocoaPods - -Add the following line to your Podfile. - -``` -pod "StatefulViewController", "~> 3.0" -``` - -Then run `pod install` with CocoaPods 0.36 or newer. - #### Manually Just drag and drop the two `.swift` files in the `StatefulViewController` folder into your project. From f143bb15fc69de685381f8c713af1580f3e4249c Mon Sep 17 00:00:00 2001 From: Matthias Buchetics Date: Mon, 1 Apr 2019 10:08:40 +0200 Subject: [PATCH 5/7] removed podspec --- StatefulViewController.podspec | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 StatefulViewController.podspec diff --git a/StatefulViewController.podspec b/StatefulViewController.podspec deleted file mode 100644 index ce56a0f..0000000 --- a/StatefulViewController.podspec +++ /dev/null @@ -1,15 +0,0 @@ -Pod::Spec.new do |s| - s.name = "StatefulViewController" - s.version = "3.0" - s.summary = "Placeholder views based on content, loading, error or empty states" - s.description = "A view controller subclass that presents placeholder views based on content, loading, error or empty states." - s.homepage = "https://github.com/aschuch/StatefulViewController" - s.license = { :type => "MIT", :file => "LICENSE" } - s.author = { "Alexander Schuch" => "alexander@schuch.me" } - s.social_media_url = "http://twitter.com/schuchalexander" - s.ios.deployment_target = "8.0" - s.tvos.deployment_target = "9.0" - s.source = { :git => "https://github.com/aschuch/StatefulViewController.git", :tag => s.version } - s.requires_arc = true - s.source_files = 'StatefulViewController/*.swift' -end From eeff69ac39489ba53d84a27fb8e487d2235ee588 Mon Sep 17 00:00:00 2001 From: Fabian Geistert Date: Fri, 13 Sep 2019 10:28:55 +0200 Subject: [PATCH 6/7] Swift Package Manager Support (#1) * update gitignore for spm * swift package * updated readme --- .gitignore | 3 +++ Package.swift | 23 +++++++++++++++++++++++ README.md | 8 ++++++++ 3 files changed, 34 insertions(+) create mode 100644 Package.swift diff --git a/.gitignore b/.gitignore index 19ccb4f..5da9a19 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ DerivedData # Carthage Carthage/Checkouts Carthage/Build + +# Swift Package Manager +.build/ \ No newline at end of file diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..8455eab --- /dev/null +++ b/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version:5.0 + +import PackageDescription + +let package = Package( + name: "StatefulViewController", + platforms: [ + .macOS(.v10_12), + .iOS(.v11), + .tvOS(.v11), + .watchOS(.v3) + ], + products: [ + .library(name: "StatefulViewController", targets: ["StatefulViewController"]) + ], + dependencies: [ + ], + targets: [ + .target(name: "StatefulViewController", dependencies: [], path: "StatefulViewController/"), + .testTarget(name: "StatefulViewControllerTests", dependencies: [], path: "StatefulViewControllerTests/") + ], + swiftLanguageVersions: [.v5] +) diff --git a/README.md b/README.md index dd3ad0a..24865c8 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,14 @@ stateMachine.transitionToState(.None, animated: true) { ## Installation +#### Swift Package Manager (Recommended) + +Add the following dependency to your `Package.swift` file: + +``` +.package(url: "https://github.com/allaboutapps/StatefulViewController.git", from: "5.1.0") +``` + #### Carthage Add the following line to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). From c74a626b5d360b40bc5b5d7ea611e1f697ebb356 Mon Sep 17 00:00:00 2001 From: Michael Wagner Date: Thu, 17 Oct 2019 19:14:12 +0200 Subject: [PATCH 7/7] feat: Replace the foregroundStore Set with an array and remove duplicates; example: Add example with an grandientOverlay --- Example.xcodeproj/project.pbxproj | 12 +- Example/Base.lproj/Main.storyboard | 143 ++++++++++++------ .../ForegroundViewStoreViewController.swift | 29 +++- Example/GradientView.swift | 46 ++++++ Example/Info.plist | 2 + .../BasicPlaceholderView.swift | 13 +- Example/PlaceholderViews/LoadingView.swift | 7 +- .../StatefulViewController.swift | 2 +- ...StatefulViewControllerImplementation.swift | 28 +++- StatefulViewController/ViewStateMachine.swift | 40 ++--- 10 files changed, 230 insertions(+), 92 deletions(-) create mode 100644 Example/GradientView.swift diff --git a/Example.xcodeproj/project.pbxproj b/Example.xcodeproj/project.pbxproj index 1453d71..d7d8594 100644 --- a/Example.xcodeproj/project.pbxproj +++ b/Example.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 523646911C6F88CF00392180 /* StatefulViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6451661A64089800108EA3 /* StatefulViewController.swift */; }; 523646921C6F88CF00392180 /* StatefulViewControllerImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC230DC1BB5BA810083B95A /* StatefulViewControllerImplementation.swift */; }; 523646931C6F88CF00392180 /* ViewStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6451671A64089800108EA3 /* ViewStateMachine.swift */; }; + D32EF03F2358D27F0001D9B5 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D32EF03E2358D27F0001D9B5 /* GradientView.swift */; }; D377D48A21D5018800C93544 /* ForegroundViewStoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D377D48921D5018800C93544 /* ForegroundViewStoreViewController.swift */; }; /* End PBXBuildFile section */ @@ -98,6 +99,7 @@ 4DE62B0B19B65AF00021630A /* ErrorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = ""; }; 4DE62B0C19B65AF00021630A /* LoadingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; 523646881C6F87B000392180 /* StatefulViewController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StatefulViewController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D32EF03E2358D27F0001D9B5 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; D377D48921D5018800C93544 /* ForegroundViewStoreViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForegroundViewStoreViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -202,6 +204,7 @@ 4D0EA4711ECAF83E00139926 /* TableViewController.swift */, 4D0EA4731ECB052000139926 /* CollectionViewController.swift */, D377D48921D5018800C93544 /* ForegroundViewStoreViewController.swift */, + D32EF03E2358D27F0001D9B5 /* GradientView.swift */, 4DE62B0819B65AF00021630A /* PlaceholderViews */, 4DE62AE519B658610021630A /* Main.storyboard */, 4D137EB619C1BE5700AC1050 /* LaunchScreen.xib */, @@ -438,6 +441,7 @@ files = ( 4DE62AE419B658610021630A /* ViewController.swift in Sources */, 4D0EA4721ECAF83E00139926 /* TableViewController.swift in Sources */, + D32EF03F2358D27F0001D9B5 /* GradientView.swift in Sources */, 4DE62B0D19B65AF00021630A /* BasicPlaceholderView.swift in Sources */, D377D48A21D5018800C93544 /* ForegroundViewStoreViewController.swift in Sources */, 4DE62AE219B658610021630A /* AppDelegate.swift in Sources */, @@ -515,7 +519,7 @@ ); INFOPLIST_FILE = StatefulViewController/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = at.allaboutapps.StatefulViewController; PRODUCT_NAME = StatefulViewController; @@ -541,7 +545,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = StatefulViewController/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = at.allaboutapps.StatefulViewController; PRODUCT_NAME = StatefulViewController; @@ -738,7 +742,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; + TVOS_DEPLOYMENT_TARGET = 10.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -764,7 +768,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; + TVOS_DEPLOYMENT_TARGET = 10.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; diff --git a/Example/Base.lproj/Main.storyboard b/Example/Base.lproj/Main.storyboard index e691035..63f3beb 100644 --- a/Example/Base.lproj/Main.storyboard +++ b/Example/Base.lproj/Main.storyboard @@ -1,11 +1,10 @@ - - - - + + - + + @@ -13,10 +12,6 @@ - - - - @@ -26,14 +21,14 @@ - + - + - - + + - + + @@ -79,11 +75,11 @@ - + - + - + - + - + - + - +