diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index 53a7452..3b0671c 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -13,7 +13,7 @@ CE7094CD269C2AEA00298AD2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE7094CB269C2AEA00298AD2 /* LaunchScreen.storyboard */; }; CE7094D6269C2B8F00298AD2 /* ExampleSceneState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7094D5269C2B8F00298AD2 /* ExampleSceneState.swift */; }; CE7094D9269C2BF900298AD2 /* SceneBox in Frameworks */ = {isa = PBXBuildFile; productRef = CE7094D8269C2BF900298AD2 /* SceneBox */; }; - CE7094DB269C390A00298AD2 /* SceneStateConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7094DA269C390A00298AD2 /* SceneStateConfiguration.swift */; }; + CE7094DB269C390A00298AD2 /* MyConfigureFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7094DA269C390A00298AD2 /* MyConfigureFile.swift */; }; CE7094DD269C393C00298AD2 /* SceneDataSharingKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7094DC269C393C00298AD2 /* SceneDataSharingKey.swift */; }; CE7094E2269C3FDB00298AD2 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7094E1269C3FDB00298AD2 /* HomeViewController.swift */; }; CE7094E4269C3FE400298AD2 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7094E3269C3FE400298AD2 /* DetailViewController.swift */; }; @@ -30,7 +30,7 @@ CE7094CC269C2AEA00298AD2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; CE7094CE269C2AEA00298AD2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; CE7094D5269C2B8F00298AD2 /* ExampleSceneState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleSceneState.swift; sourceTree = ""; }; - CE7094DA269C390A00298AD2 /* SceneStateConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneStateConfiguration.swift; sourceTree = ""; }; + CE7094DA269C390A00298AD2 /* MyConfigureFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyConfigureFile.swift; sourceTree = ""; }; CE7094DC269C393C00298AD2 /* SceneDataSharingKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDataSharingKey.swift; sourceTree = ""; }; CE7094E1269C3FDB00298AD2 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; CE7094E3269C3FE400298AD2 /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = ""; }; @@ -86,7 +86,7 @@ isa = PBXGroup; children = ( CE7094D5269C2B8F00298AD2 /* ExampleSceneState.swift */, - CE7094DA269C390A00298AD2 /* SceneStateConfiguration.swift */, + CE7094DA269C390A00298AD2 /* MyConfigureFile.swift */, CE7094DC269C393C00298AD2 /* SceneDataSharingKey.swift */, ); path = SceneConfiguration; @@ -196,7 +196,7 @@ files = ( CE7094D6269C2B8F00298AD2 /* ExampleSceneState.swift in Sources */, CE7094DD269C393C00298AD2 /* SceneDataSharingKey.swift in Sources */, - CE7094DB269C390A00298AD2 /* SceneStateConfiguration.swift in Sources */, + CE7094DB269C390A00298AD2 /* MyConfigureFile.swift in Sources */, CE7094EA269C4D9700298AD2 /* Color.swift in Sources */, CE7094E6269C406C00298AD2 /* HomeViewModel.swift in Sources */, CE7094E8269C407400298AD2 /* DetailViewModel.swift in Sources */, diff --git a/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index b32a448..17bc4bd 100644 --- a/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/lumiasaki/SceneBox.git", "state": { "branch": null, - "revision": "6586041e5e3f1c12a928d90eb7f46b9ccebf04ae", - "version": "0.3.1" + "revision": "e6f19e17b3e19f271c189fb0c5e95c5d50e46bf4", + "version": "0.4.0" } } ] diff --git a/Example/Example/SceneConfiguration/ExampleSceneState.swift b/Example/Example/SceneConfiguration/ExampleSceneState.swift index bf87eb5..19331af 100644 --- a/Example/Example/SceneConfiguration/ExampleSceneState.swift +++ b/Example/Example/SceneConfiguration/ExampleSceneState.swift @@ -16,11 +16,4 @@ struct ExampleSceneState: RawRepresentable, Hashable, Equatable { static let home = ExampleSceneState(rawValue: NavigationExtension.entry) static let detail = ExampleSceneState(rawValue: 1) - static let termination = ExampleSceneState(rawValue: NavigationExtension.termination) -} - -extension ExampleSceneState: CaseIterable { - - /// Help to register all states. - static var allCases: [ExampleSceneState] { [.home, .detail, .termination] } } diff --git a/Example/Example/SceneConfiguration/MyConfigureFile.swift b/Example/Example/SceneConfiguration/MyConfigureFile.swift new file mode 100644 index 0000000..f282745 --- /dev/null +++ b/Example/Example/SceneConfiguration/MyConfigureFile.swift @@ -0,0 +1,24 @@ +// +// MyConfigureFile.swift +// Example +// +// Created by Lumia_Saki on 2021/7/12. +// Copyright © 2021年 tianren.zhu. All rights reserved. +// + +import Foundation +import SceneBox + +/// Configuration file for this example project. +struct MyConfigureFile: ConfigurationFile { + + static var sceneStates: Set = Set([ + ExampleSceneState.home.rawValue, + ExampleSceneState.detail.rawValue + ]) + + static var extensions: [Extension] = [ + NavigationExtension(), + SharedStateExtension(stateValue: SceneData()) + ] +} diff --git a/Example/Example/SceneConfiguration/SceneStateConfiguration.swift b/Example/Example/SceneConfiguration/SceneStateConfiguration.swift deleted file mode 100644 index 71344a2..0000000 --- a/Example/Example/SceneConfiguration/SceneStateConfiguration.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// SceneStateConfiguration.swift -// Example -// -// Created by Lumia_Saki on 2021/7/12. -// Copyright © 2021年 tianren.zhu. All rights reserved. -// - -import Foundation - -/// Configuration of SceneBox for this submission. -struct SceneStateConfiguration { - - private(set) var sceneStates: [ExampleSceneState] - private(set) var currentSceneStateMap: [Int : UUID] - - init(sceneStates: [ExampleSceneState]) { - self.sceneStates = sceneStates - self.currentSceneStateMap = sceneStates.reduce([:]) { - $0.merging([$1.rawValue : UUID()]) { $1 } - } - } - - /// Get identifier to `lazyAdd` the scene to SceneBox. - /// - Parameter state: State declared in `GithubDMSceneState` - /// - Returns: Auto-generated identifier for a scene, aka view controller. - func identifier(with state: ExampleSceneState) -> UUID { - guard let identifier = currentSceneStateMap[state.rawValue] else { - fatalError("can not find identifier for \(state)") - } - - return identifier - } -} diff --git a/Example/Example/SceneDelegate.swift b/Example/Example/SceneDelegate.swift index 2c4afbb..3a04430 100644 --- a/Example/Example/SceneDelegate.swift +++ b/Example/Example/SceneDelegate.swift @@ -30,17 +30,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window?.makeKeyAndVisible() // configure SceneBox with some configurations - let sceneStateConfiguration = SceneStateConfiguration(sceneStates: ExampleSceneState.allCases) - - let sceneBoxConfiguration = Configuration(stateSceneIdentifierTable: sceneStateConfiguration.currentSceneStateMap).withBuiltInNavigationExtension().withBuiltInSharedStateExtension(stateValue: SceneData()) - - sceneBoxConfiguration.navigationController = navigationController + let sceneBoxConfiguration = try! Configuration(configurationFile: MyConfigureFile.self) let sceneBox = SceneBox(configuration: sceneBoxConfiguration) { scene, sceneBox in self.navigationController.pushViewController(scene, animated: false) } exit: { _ in } - setUpSceneStateIdentifierTable(for: sceneBox, sceneStateConfiguration: sceneStateConfiguration) + setUpSceneStateIdentifierTable(for: sceneBox) try? Executor.shared.execute(box: sceneBox) } @@ -79,10 +75,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { extension SceneDelegate { // The real set up place for view controllers and view models, it's a great tool for decoupling - private func setUpSceneStateIdentifierTable(for box: SceneBox, sceneStateConfiguration: SceneStateConfiguration) { + private func setUpSceneStateIdentifierTable(for box: SceneBox) { // home do { - box.lazyAdd(identifier: sceneStateConfiguration.identifier(with: .home)) { + box.lazyAdd(sceneState: ExampleSceneState.home.rawValue) { let viewModel = HomeViewModel() let viewController = HomeViewController(viewModel: viewModel) viewModel.scene = viewController @@ -93,7 +89,7 @@ extension SceneDelegate { // detail do { - box.lazyAdd(identifier: sceneStateConfiguration.identifier(with: .detail)) { + box.lazyAdd(sceneState: ExampleSceneState.detail.rawValue) { let viewModel = DetailViewModel() let viewController = DetailViewController(viewModel: viewModel) viewModel.scene = viewController diff --git a/README.md b/README.md index 2618d53..4511134 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Based on these two pain points, I conceived the framework to enable us to develo To integrate using Apple's SPM, add following as a dependency to your Target. -`.package(url: "https://github.com/lumiasaki/SceneBox.git", .upToNextMajor(from: "0.4.0"))` +`.package(url: "https://github.com/lumiasaki/SceneBox.git", .upToNextMajor(from: "0.4.1"))` ## How to use diff --git a/Sources/SceneBox/Extension/Core/NavigationExtension.swift b/Sources/SceneBox/Extension/Core/NavigationExtension.swift index ba98204..f2a15e3 100644 --- a/Sources/SceneBox/Extension/Core/NavigationExtension.swift +++ b/Sources/SceneBox/Extension/Core/NavigationExtension.swift @@ -75,14 +75,16 @@ public final class NavigationExtension: NSObject, Extension { // insert entry into state trace stateTrace.append(Self.entry) - previousNavigationControllerDelegate = sceneBox?.navigationController?.delegate - sceneBox?.navigationController?.delegate = self - sceneBox?.watch(on: EventBus.EventName.getStatesRequest, messageType: Void.self, next: { [unowned self] _ in self.sceneBox?.dispatch(event: EventBus.EventName.getStatesResponse, message: NavigationGetScenesMessage(scenes: stateTrace)) }) } + public func sceneBoxReady() { + previousNavigationControllerDelegate = sceneBox?.navigationController?.delegate + sceneBox?.navigationController?.delegate = self + } + // MARK: - Private fileprivate func transit(to state: Int) { diff --git a/Sources/SceneBox/LifeCycle/ExtensionLifeCycle.swift b/Sources/SceneBox/LifeCycle/ExtensionLifeCycle.swift index 2af646d..768d401 100644 --- a/Sources/SceneBox/LifeCycle/ExtensionLifeCycle.swift +++ b/Sources/SceneBox/LifeCycle/ExtensionLifeCycle.swift @@ -17,5 +17,5 @@ public protocol ExtensionLifeCycle { public extension ExtensionLifeCycle { - func extensionDidMount() { } + func extensionDidMount() { } } diff --git a/Sources/SceneBox/LifeCycle/SceneBoxLifeCycle.swift b/Sources/SceneBox/LifeCycle/SceneBoxLifeCycle.swift index 54d1d36..cab1185 100644 --- a/Sources/SceneBox/LifeCycle/SceneBoxLifeCycle.swift +++ b/Sources/SceneBox/LifeCycle/SceneBoxLifeCycle.swift @@ -11,11 +11,15 @@ import Foundation /// Life cycle of the a scene box. public protocol SceneBoxLifeCycle { + /// Called at last step in `SceneBox.execute`. + func sceneBoxReady() + /// Called when transit to the `terminate` state, the scene box will be terminated. func sceneBoxWillTerminate() } public extension SceneBoxLifeCycle { + func sceneBoxReady() { } func sceneBoxWillTerminate() { } } diff --git a/Sources/SceneBox/SceneBox.swift b/Sources/SceneBox/SceneBox.swift index 0e57bac..703723f 100644 --- a/Sources/SceneBox/SceneBox.swift +++ b/Sources/SceneBox/SceneBox.swift @@ -103,6 +103,10 @@ public final class SceneBox { } self.navigationController = navigationController + + // notify ready event + scenesIdentifierMap.values.forEach { $0.sceneBoxReady() } + extensions.values.forEach { $0.sceneBoxReady() } } // MARK: - Private Methods