From 68a28f6ec477d5b1ac1670bf441e9ce5f50e0074 Mon Sep 17 00:00:00 2001 From: Evgeny Kazaev Date: Fri, 5 Apr 2019 00:43:01 +0100 Subject: [PATCH] Integrated Slather --- .slather.yml | 5 + .travis.yml | 5 +- Example/Podfile | 2 + Example/Podfile.lock | 2 +- Example/Pods/Manifest.lock | 2 +- Example/Pods/Pods.xcodeproj/project.pbxproj | 534 +++--- .../xcschemes/RouteComposer.xcscheme | 1 + README.md | 2 +- docs/tests/AbstractFactory.swift.html | 262 +++ docs/tests/Action.swift.html | 182 ++ docs/tests/ActionBox.swift.html | 257 +++ .../tests/ActionConnectingAssembly.swift.html | 202 +++ docs/tests/ActionResult.swift.html | 197 +++ docs/tests/ActionToStepIntegrator.swift.html | 322 ++++ docs/tests/AnyFactoryBox.swift.html | 277 +++ docs/tests/Array+Extension.swift.html | 247 +++ docs/tests/BaseEntitiesCollector.swift.html | 162 ++ docs/tests/BaseStep.swift.html | 437 +++++ docs/tests/ChainAssembly.swift.html | 142 ++ docs/tests/ChildCoordinator.swift.html | 177 ++ docs/tests/ClassFinder.swift.html | 222 +++ docs/tests/ClassNameFactory.swift.html | 267 +++ docs/tests/ClassWithContextFinder.swift.html | 232 +++ docs/tests/CompleteFactory.swift.html | 237 +++ docs/tests/CompleteFactoryAssembly.swift.html | 562 ++++++ .../CompleteFactoryChainAssembly.swift.html | 582 +++++++ docs/tests/ContainerActionBox.swift.html | 422 +++++ docs/tests/ContainerFactory.swift.html | 457 +++++ docs/tests/ContainerFactoryBox.swift.html | 277 +++ docs/tests/ContainerStepAssembly.swift.html | 472 +++++ .../ContainerStepChainAssembly.swift.html | 237 +++ docs/tests/ContextAccepting.swift.html | 207 +++ docs/tests/ContextSettingTask.swift.html | 142 ++ docs/tests/ContextTask.swift.html | 457 +++++ docs/tests/ContextTaskBox.swift.html | 227 +++ docs/tests/ContextTaskMultiplexer.swift.html | 197 +++ docs/tests/CustomWindowProvider.swift.html | 117 ++ docs/tests/DefaultLogger.swift.html | 367 ++++ docs/tests/DefaultRouter+Extension.swift.html | 1537 +++++++++++++++++ docs/tests/DefaultRouter.swift.html | 1297 ++++++++++++++ docs/tests/DefaultStackIterator.swift.html | 332 ++++ .../DelayedIntegrationFactory.swift.html | 247 +++ docs/tests/DestinationStep.swift.html | 322 ++++ ...issalMethodProvidingContextTask.swift.html | 167 ++ docs/tests/Dismissible.swift.html | 442 +++++ docs/tests/Factory.swift.html | 392 +++++ docs/tests/FactoryBox.swift.html | 197 +++ docs/tests/Finder.swift.html | 257 +++ docs/tests/FinderBox.swift.html | 172 ++ docs/tests/FinderFactory.swift.html | 197 +++ docs/tests/GeneralStep.swift.html | 412 +++++ docs/tests/GenericStepAssembly.swift.html | 257 +++ docs/tests/InlineTasks.swift.html | 552 ++++++ docs/tests/InstanceFinder.swift.html | 157 ++ docs/tests/InterceptorMultiplexer.swift.html | 282 +++ docs/tests/InterceptorResult.swift.html | 192 ++ docs/tests/KeyWindowProvider.swift.html | 137 ++ docs/tests/LastStepInChainAssembly.swift.html | 227 +++ docs/tests/MainThreadChecking.swift.html | 127 ++ .../NavigationController+Extension.swift.html | 247 +++ .../NavigationControllerFactory.swift.html | 222 +++ .../tests/NavigationControllerStep.swift.html | 102 ++ .../NavigationDelayInterceptor.swift.html | 417 +++++ docs/tests/NilFactory.swift.html | 172 ++ docs/tests/NilFinder.swift.html | 157 ++ docs/tests/PostRoutingTask.swift.html | 292 ++++ docs/tests/PostRoutingTaskBox.swift.html | 192 ++ .../PostRoutingTaskMultiplexer.swift.html | 142 ++ docs/tests/PreparableEntity.swift.html | 132 ++ docs/tests/PresentingFinder.swift.html | 147 ++ docs/tests/Router.swift.html | 282 +++ docs/tests/RoutingError.swift.html | 327 ++++ docs/tests/RoutingInterceptor.swift.html | 527 ++++++ docs/tests/RoutingInterceptorBox.swift.html | 247 +++ docs/tests/RoutingResult.swift.html | 182 ++ docs/tests/SearchOptions.swift.html | 407 +++++ docs/tests/SimpleContainerFactory.swift.html | 207 +++ docs/tests/SingleContainerStep.swift.html | 472 +++++ docs/tests/SingleNavigationRouter.swift.html | 457 +++++ docs/tests/SingleStep.swift.html | 472 +++++ docs/tests/SplitControllerFactory.swift.html | 322 ++++ docs/tests/SplitControllerStep.swift.html | 102 ++ .../SplitViewController+Extension.swift.html | 357 ++++ docs/tests/StackIteratingFinder.swift.html | 247 +++ docs/tests/StepAssembly.swift.html | 477 +++++ docs/tests/StepChainAssembly.swift.html | 237 +++ docs/tests/StoryboardFactory.swift.html | 312 ++++ docs/tests/SwitchAssembly.swift.html | 737 ++++++++ docs/tests/SwitcherStep.swift.html | 177 ++ docs/tests/TabBarControllerFactory.swift.html | 222 +++ docs/tests/TabBarControllerStep.swift.html | 102 ++ .../TabBarViewController+Extension.swift.html | 262 +++ docs/tests/TaskCollector.swift.html | 217 +++ .../UINavigationController+Action.swift.html | 512 ++++++ .../UISplitViewController+Action.swift.html | 447 +++++ .../UITabBarController+Action.swift.html | 487 ++++++ docs/tests/UIViewController+Action.swift.html | 952 ++++++++++ .../UIViewController+Extension.swift.html | 527 ++++++ docs/tests/UIWindow+Extension.swift.html | 137 ++ docs/tests/XibFactory.swift.html | 197 +++ docs/tests/highlight.pack.js | 1 + docs/tests/index.html | 767 ++++++++ docs/tests/list.min.js | 1 + docs/tests/logo.jpg | Bin 0 -> 64627 bytes docs/tests/slather.css | 316 ++++ 105 files changed, 30645 insertions(+), 272 deletions(-) create mode 100644 .slather.yml create mode 100644 docs/tests/AbstractFactory.swift.html create mode 100644 docs/tests/Action.swift.html create mode 100644 docs/tests/ActionBox.swift.html create mode 100644 docs/tests/ActionConnectingAssembly.swift.html create mode 100644 docs/tests/ActionResult.swift.html create mode 100644 docs/tests/ActionToStepIntegrator.swift.html create mode 100644 docs/tests/AnyFactoryBox.swift.html create mode 100644 docs/tests/Array+Extension.swift.html create mode 100644 docs/tests/BaseEntitiesCollector.swift.html create mode 100644 docs/tests/BaseStep.swift.html create mode 100644 docs/tests/ChainAssembly.swift.html create mode 100644 docs/tests/ChildCoordinator.swift.html create mode 100644 docs/tests/ClassFinder.swift.html create mode 100644 docs/tests/ClassNameFactory.swift.html create mode 100644 docs/tests/ClassWithContextFinder.swift.html create mode 100644 docs/tests/CompleteFactory.swift.html create mode 100644 docs/tests/CompleteFactoryAssembly.swift.html create mode 100644 docs/tests/CompleteFactoryChainAssembly.swift.html create mode 100644 docs/tests/ContainerActionBox.swift.html create mode 100644 docs/tests/ContainerFactory.swift.html create mode 100644 docs/tests/ContainerFactoryBox.swift.html create mode 100644 docs/tests/ContainerStepAssembly.swift.html create mode 100644 docs/tests/ContainerStepChainAssembly.swift.html create mode 100644 docs/tests/ContextAccepting.swift.html create mode 100644 docs/tests/ContextSettingTask.swift.html create mode 100644 docs/tests/ContextTask.swift.html create mode 100644 docs/tests/ContextTaskBox.swift.html create mode 100644 docs/tests/ContextTaskMultiplexer.swift.html create mode 100644 docs/tests/CustomWindowProvider.swift.html create mode 100644 docs/tests/DefaultLogger.swift.html create mode 100644 docs/tests/DefaultRouter+Extension.swift.html create mode 100644 docs/tests/DefaultRouter.swift.html create mode 100644 docs/tests/DefaultStackIterator.swift.html create mode 100644 docs/tests/DelayedIntegrationFactory.swift.html create mode 100644 docs/tests/DestinationStep.swift.html create mode 100644 docs/tests/DismissalMethodProvidingContextTask.swift.html create mode 100644 docs/tests/Dismissible.swift.html create mode 100644 docs/tests/Factory.swift.html create mode 100644 docs/tests/FactoryBox.swift.html create mode 100644 docs/tests/Finder.swift.html create mode 100644 docs/tests/FinderBox.swift.html create mode 100644 docs/tests/FinderFactory.swift.html create mode 100644 docs/tests/GeneralStep.swift.html create mode 100644 docs/tests/GenericStepAssembly.swift.html create mode 100644 docs/tests/InlineTasks.swift.html create mode 100644 docs/tests/InstanceFinder.swift.html create mode 100644 docs/tests/InterceptorMultiplexer.swift.html create mode 100644 docs/tests/InterceptorResult.swift.html create mode 100644 docs/tests/KeyWindowProvider.swift.html create mode 100644 docs/tests/LastStepInChainAssembly.swift.html create mode 100644 docs/tests/MainThreadChecking.swift.html create mode 100644 docs/tests/NavigationController+Extension.swift.html create mode 100644 docs/tests/NavigationControllerFactory.swift.html create mode 100644 docs/tests/NavigationControllerStep.swift.html create mode 100644 docs/tests/NavigationDelayInterceptor.swift.html create mode 100644 docs/tests/NilFactory.swift.html create mode 100644 docs/tests/NilFinder.swift.html create mode 100644 docs/tests/PostRoutingTask.swift.html create mode 100644 docs/tests/PostRoutingTaskBox.swift.html create mode 100644 docs/tests/PostRoutingTaskMultiplexer.swift.html create mode 100644 docs/tests/PreparableEntity.swift.html create mode 100644 docs/tests/PresentingFinder.swift.html create mode 100644 docs/tests/Router.swift.html create mode 100644 docs/tests/RoutingError.swift.html create mode 100644 docs/tests/RoutingInterceptor.swift.html create mode 100644 docs/tests/RoutingInterceptorBox.swift.html create mode 100644 docs/tests/RoutingResult.swift.html create mode 100644 docs/tests/SearchOptions.swift.html create mode 100644 docs/tests/SimpleContainerFactory.swift.html create mode 100644 docs/tests/SingleContainerStep.swift.html create mode 100644 docs/tests/SingleNavigationRouter.swift.html create mode 100644 docs/tests/SingleStep.swift.html create mode 100644 docs/tests/SplitControllerFactory.swift.html create mode 100644 docs/tests/SplitControllerStep.swift.html create mode 100644 docs/tests/SplitViewController+Extension.swift.html create mode 100644 docs/tests/StackIteratingFinder.swift.html create mode 100644 docs/tests/StepAssembly.swift.html create mode 100644 docs/tests/StepChainAssembly.swift.html create mode 100644 docs/tests/StoryboardFactory.swift.html create mode 100644 docs/tests/SwitchAssembly.swift.html create mode 100644 docs/tests/SwitcherStep.swift.html create mode 100644 docs/tests/TabBarControllerFactory.swift.html create mode 100644 docs/tests/TabBarControllerStep.swift.html create mode 100644 docs/tests/TabBarViewController+Extension.swift.html create mode 100644 docs/tests/TaskCollector.swift.html create mode 100644 docs/tests/UINavigationController+Action.swift.html create mode 100644 docs/tests/UISplitViewController+Action.swift.html create mode 100644 docs/tests/UITabBarController+Action.swift.html create mode 100644 docs/tests/UIViewController+Action.swift.html create mode 100644 docs/tests/UIViewController+Extension.swift.html create mode 100644 docs/tests/UIWindow+Extension.swift.html create mode 100644 docs/tests/XibFactory.swift.html create mode 100644 docs/tests/highlight.pack.js create mode 100644 docs/tests/index.html create mode 100644 docs/tests/list.min.js create mode 100644 docs/tests/logo.jpg create mode 100644 docs/tests/slather.css diff --git a/.slather.yml b/.slather.yml new file mode 100644 index 000000000..61300b2be --- /dev/null +++ b/.slather.yml @@ -0,0 +1,5 @@ +xcodeproj: ./Example/RouteComposer.xcodeproj +workspace: ./Example/RouteComposer.xcworkspace/ +scheme: RouteComposer-Example +source_directory: ./RouteComposer/Classes +binary_basename: RouteComposer \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 9024579cf..b27217caf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,17 @@ # references: # * http://www.objc.io/issue-6/travis-ci.html # * https://github.com/supermarin/xcpretty#usage +# *slather coverage --html --output-directory ./docs/tests --arch x86_64 osx_image: xcode10.2 language: swift cache: cocoapods podfile: Example/Podfile before_install: +- gem install slather - gem install cocoapods # Since Travis is not always on latest version - pod install --project-directory=Example script: -- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/RouteComposer.xcworkspace -scheme RouteComposer-Example -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone X,OS=12.1' ONLY_ACTIVE_ARCH=NO | xcpretty +- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/RouteComposer.xcworkspace -scheme RouteComposer-Example -sdk iphonesimulator -derivedDataPath ${TRAVIS_BUILD_DIR}/myDerivedData -destination 'platform=iOS Simulator,name=iPhone X,OS=12.2' ONLY_ACTIVE_ARCH=YES | xcpretty - pod lib lint +after_success: slather coverage -t -b ${TRAVIS_BUILD_DIR}/myDerivedData --arch x86_64 --verbose diff --git a/Example/Podfile b/Example/Podfile index 0913b1b69..b43e8f867 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,6 +1,8 @@ platform :ios, '9.3' use_frameworks! +plugin 'slather' + target 'RouteComposer_Example' do pod 'RouteComposer', :path => '../' diff --git a/Example/Podfile.lock b/Example/Podfile.lock index c358aefc4..a35d1b618 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -11,6 +11,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: RouteComposer: 2e3a290122f0ef9926bdec015297c73ad01c721c -PODFILE CHECKSUM: 42df1440502a2c666dc2402d2027b25de2a00f46 +PODFILE CHECKSUM: 6dc3a094906d5a0f701bcb325869e4a05ad2ae57 COCOAPODS: 1.6.0 diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index c358aefc4..a35d1b618 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -11,6 +11,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: RouteComposer: 2e3a290122f0ef9926bdec015297c73ad01c721c -PODFILE CHECKSUM: 42df1440502a2c666dc2402d2027b25de2a00f46 +PODFILE CHECKSUM: 6dc3a094906d5a0f701bcb325869e4a05ad2ae57 COCOAPODS: 1.6.0 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 34fe1a57f..752875ab0 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -154,413 +154,413 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 00E5461FEF31C1816FB3C09F2AD52ACF /* Logger.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Logger.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Logger.html; sourceTree = ""; }; - 013FAE5AEEFF51E757763C08F58D9A6B /* ActionConnecting.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ActionConnecting.html; path = docs/Protocols/ActionConnecting.html; sourceTree = ""; }; + 00E5461FEF31C1816FB3C09F2AD52ACF /* Logger.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Logger.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Logger.html; sourceTree = ""; }; + 013FAE5AEEFF51E757763C08F58D9A6B /* ActionConnecting.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ActionConnecting.html; path = docs/Protocols/ActionConnecting.html; sourceTree = ""; }; 01D7AE6173BCCDEF62B739ED5EE63AD4 /* BaseStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BaseStep.swift; sourceTree = ""; }; - 01DF8A772FB7CCC491C7B70522212AAD /* Steps.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Steps.html; path = docs/Steps.html; sourceTree = ""; }; - 025B763A96210137551DAFB8761949E5 /* InstanceFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InstanceFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/InstanceFinder.html; sourceTree = ""; }; - 02A6B5B9CB9A7C5FBC75A3459BC67F3C /* ContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContextTask.html; path = docs/Protocols/ContextTask.html; sourceTree = ""; }; - 039C77D67C58A94D13B098023042E658 /* AddTabAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = AddTabAction.html; path = docs/Structs/TabBarControllerActions/AddTabAction.html; sourceTree = ""; }; - 03A58AF36ED9F939C7286FA21E493F70 /* CompleteFactoryChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = CompleteFactoryChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/CompleteFactoryChainAssembly.html; sourceTree = ""; }; - 03FB8D6EEFB7D54B71C500E1CF22C0BC /* InlineInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InlineInterceptor.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/InlineInterceptor.html; sourceTree = ""; }; - 04587D4E43FAFD320CA580D30A3BFA9D /* ActionToStepIntegrator.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ActionToStepIntegrator.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/ActionToStepIntegrator.html; sourceTree = ""; }; + 01DF8A772FB7CCC491C7B70522212AAD /* Steps.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Steps.html; path = docs/Steps.html; sourceTree = ""; }; + 025B763A96210137551DAFB8761949E5 /* InstanceFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = InstanceFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/InstanceFinder.html; sourceTree = ""; }; + 02A6B5B9CB9A7C5FBC75A3459BC67F3C /* ContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContextTask.html; path = docs/Protocols/ContextTask.html; sourceTree = ""; }; + 039C77D67C58A94D13B098023042E658 /* AddTabAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = AddTabAction.html; path = docs/Structs/TabBarControllerActions/AddTabAction.html; sourceTree = ""; }; + 03A58AF36ED9F939C7286FA21E493F70 /* CompleteFactoryChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = CompleteFactoryChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/CompleteFactoryChainAssembly.html; sourceTree = ""; }; + 03FB8D6EEFB7D54B71C500E1CF22C0BC /* InlineInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = InlineInterceptor.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/InlineInterceptor.html; sourceTree = ""; }; + 04587D4E43FAFD320CA580D30A3BFA9D /* ActionToStepIntegrator.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ActionToStepIntegrator.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/ActionToStepIntegrator.html; sourceTree = ""; }; 045A2766DD01E7A861A8DAF5C61AFE6D /* StackIteratingFinder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StackIteratingFinder.swift; sourceTree = ""; }; - 04953C7F4B65EA96F4793860CACFCF43 /* ActionToStepIntegrator.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ActionToStepIntegrator.html; path = docs/Classes/ActionToStepIntegrator.html; sourceTree = ""; }; - 04BFD918380B117FB3EA69BF1AC09AF4 /* PresentingFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PresentingFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/PresentingFinder.html; sourceTree = ""; }; + 04953C7F4B65EA96F4793860CACFCF43 /* ActionToStepIntegrator.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ActionToStepIntegrator.html; path = docs/Classes/ActionToStepIntegrator.html; sourceTree = ""; }; + 04BFD918380B117FB3EA69BF1AC09AF4 /* PresentingFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = PresentingFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/PresentingFinder.html; sourceTree = ""; }; 04C8BBB8754217FA3C5A90DCFC34CB05 /* AnyFactoryBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyFactoryBox.swift; sourceTree = ""; }; 05128C494CA41D07A2106C7C6C2BEE00 /* ContextTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContextTask.swift; path = RouteComposer/Classes/ContextTask.swift; sourceTree = ""; }; 05463B68954A3EC6254D1B8BE08AF3C5 /* RoutingInterceptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RoutingInterceptor.swift; path = RouteComposer/Classes/RoutingInterceptor.swift; sourceTree = ""; }; - 058EF16EA3C5960484756C5488EF5315 /* Strategy.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Strategy.html; path = docs/Structs/NavigationDelayingInterceptor/Strategy.html; sourceTree = ""; }; + 058EF16EA3C5960484756C5488EF5315 /* Strategy.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Strategy.html; path = docs/Structs/NavigationDelayingInterceptor/Strategy.html; sourceTree = ""; }; 05BB212958A3C39384391D2A7F21EC53 /* XibFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = XibFactory.swift; sourceTree = ""; }; 06E1C2D013612A0F26046E327B75E845 /* Pods-RouteComposer_Example-RouteComposer_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-RouteComposer_Example-RouteComposer_Tests-acknowledgements.plist"; sourceTree = ""; }; - 06FAF9E88352A53E628F8BE4947DB09C /* SingleNavigationRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SingleNavigationRouter.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SingleNavigationRouter.html; sourceTree = ""; }; - 0743E270F40FB156988DAB68E3EE30FF /* PushToDetailsAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PushToDetailsAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SplitViewControllerActions/PushToDetailsAction.html; sourceTree = ""; }; + 06FAF9E88352A53E628F8BE4947DB09C /* SingleNavigationRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SingleNavigationRouter.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SingleNavigationRouter.html; sourceTree = ""; }; + 0743E270F40FB156988DAB68E3EE30FF /* PushToDetailsAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = PushToDetailsAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SplitViewControllerActions/PushToDetailsAction.html; sourceTree = ""; }; 0759A1E7D44952A87BD9D24267E42306 /* dash.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = dash.png; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/img/dash.png; sourceTree = ""; }; 08028DD17BE8145825B35AD22AD7FA4B /* NavigationDelayInterceptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NavigationDelayInterceptor.swift; sourceTree = ""; }; - 08783A3741A2AE14F06E8DB74E55C2B2 /* InlinePostTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InlinePostTask.html; path = docs/Structs/InlinePostTask.html; sourceTree = ""; }; + 08783A3741A2AE14F06E8DB74E55C2B2 /* InlinePostTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = InlinePostTask.html; path = docs/Structs/InlinePostTask.html; sourceTree = ""; }; 08C03815A2893E9CA2F70B5784BE29BA /* PerformableStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformableStep.swift; sourceTree = ""; }; 091A74F3F399C891FA7B14D96E4BA616 /* AnyFinder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyFinder.swift; sourceTree = ""; }; 093A5D01988A46187EFB0072FF253F90 /* DefaultLogger+LogLevel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "DefaultLogger+LogLevel.swift"; sourceTree = ""; }; 0AAF5AB13038207C97E83F09DA225BE8 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = ""; }; - 0D41DBE5379A2581554DEA3BA0D65E61 /* ContextSettingTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContextSettingTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ContextSettingTask.html; sourceTree = ""; }; - 0D7D66287D0E9A77311642E14569F6B8 /* ViewControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ViewControllerActions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ViewControllerActions.html; sourceTree = ""; }; - 0E740524B75E12ABB74BDF9884A70778 /* ContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContextTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContextTask.html; sourceTree = ""; }; - 0EE14AAC2070C281E33701369B7A872D /* GeneralAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = GeneralAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/GeneralAction.html; sourceTree = ""; }; - 1012299BCAA45D23B98CA188B5946CEF /* TabBarControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = TabBarControllerActions.html; path = docs/Structs/TabBarControllerActions.html; sourceTree = ""; }; - 108297AD1878A02D49470D1F1984682E /* Other Protocols.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Protocols.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Protocols.html"; sourceTree = ""; }; - 109AB8FF1B72D8B2FB4EA9C31ED523F3 /* Extras.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Extras.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extras.html; sourceTree = ""; }; + 0D41DBE5379A2581554DEA3BA0D65E61 /* ContextSettingTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContextSettingTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ContextSettingTask.html; sourceTree = ""; }; + 0D7D66287D0E9A77311642E14569F6B8 /* ViewControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ViewControllerActions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ViewControllerActions.html; sourceTree = ""; }; + 0E740524B75E12ABB74BDF9884A70778 /* ContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContextTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContextTask.html; sourceTree = ""; }; + 0EE14AAC2070C281E33701369B7A872D /* GeneralAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = GeneralAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/GeneralAction.html; sourceTree = ""; }; + 1012299BCAA45D23B98CA188B5946CEF /* TabBarControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = TabBarControllerActions.html; path = docs/Structs/TabBarControllerActions.html; sourceTree = ""; }; + 108297AD1878A02D49470D1F1984682E /* Other Protocols.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Other Protocols.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Protocols.html"; sourceTree = ""; }; + 109AB8FF1B72D8B2FB4EA9C31ED523F3 /* Extras.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Extras.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extras.html; sourceTree = ""; }; 11D78D26208470DB86BE752954D6907E /* GenericStepAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GenericStepAssembly.swift; sourceTree = ""; }; - 122F90DC63167D3791FF41F75B4135A5 /* ContextAccepting.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContextAccepting.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContextAccepting.html; sourceTree = ""; }; - 129730F12BD913694735E5FC2D1F053B /* PushAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PushAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerActions/PushAction.html; sourceTree = ""; }; + 122F90DC63167D3791FF41F75B4135A5 /* ContextAccepting.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContextAccepting.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContextAccepting.html; sourceTree = ""; }; + 129730F12BD913694735E5FC2D1F053B /* PushAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = PushAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerActions/PushAction.html; sourceTree = ""; }; 12CC0D7F67029F8C7207C72678272148 /* NilFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NilFactory.swift; sourceTree = ""; }; - 13AC9EA99FB3C9873E238274E46E4243 /* PushReplacingLastAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PushReplacingLastAction.html; path = docs/Structs/NavigationControllerActions/PushReplacingLastAction.html; sourceTree = ""; }; - 15BAEAB8E528D588AD03BD3C0B747213 /* ClassFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ClassFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ClassFinder.html; sourceTree = ""; }; - 15DFC171D156C6BDC22D38D96B38F581 /* StoryboardFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StoryboardFactory.html; path = docs/Structs/StoryboardFactory.html; sourceTree = ""; }; + 13AC9EA99FB3C9873E238274E46E4243 /* PushReplacingLastAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = PushReplacingLastAction.html; path = docs/Structs/NavigationControllerActions/PushReplacingLastAction.html; sourceTree = ""; }; + 15BAEAB8E528D588AD03BD3C0B747213 /* ClassFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ClassFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ClassFinder.html; sourceTree = ""; }; + 15DFC171D156C6BDC22D38D96B38F581 /* StoryboardFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = StoryboardFactory.html; path = docs/Structs/StoryboardFactory.html; sourceTree = ""; }; 16B6E10B3105A7ED40E75F088F8F9314 /* RoutingInterceptable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RoutingInterceptable.swift; path = RouteComposer/Classes/RoutingInterceptable.swift; sourceTree = ""; }; - 16F08D4E59D527481A95DD4DE88CF548 /* DefaultRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DefaultRouter.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultRouter.html; sourceTree = ""; }; - 16F539C479E89687E4C31FA6F9216085 /* InterceptableRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InterceptableRouter.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/InterceptableRouter.html; sourceTree = ""; }; - 171143FF255EAFCE92AFD7B2A773B2C7 /* Tasks.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Tasks.html; path = docs/Tasks.html; sourceTree = ""; }; - 17652CA43D0C7A8AE4BDEEF4CE134EAE /* UITabBarController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UITabBarController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UITabBarController.html; sourceTree = ""; }; - 17DE011BF898A9DF81E945B7546201AE /* Additional Assemblies.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Additional Assemblies.html"; path = "docs/Additional Assemblies.html"; sourceTree = ""; }; - 1871DA99CC86F3DC013B7BE150857130 /* Dismissible.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Dismissible.html; path = docs/Protocols/Dismissible.html; sourceTree = ""; }; - 18EA8CD294BF81276A4CF1E9FC27304A /* CustomWindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; name = CustomWindowProvider.html; path = docs/Structs/CustomWindowProvider.html; sourceTree = ""; }; + 16F08D4E59D527481A95DD4DE88CF548 /* DefaultRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = DefaultRouter.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultRouter.html; sourceTree = ""; }; + 16F539C479E89687E4C31FA6F9216085 /* InterceptableRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = InterceptableRouter.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/InterceptableRouter.html; sourceTree = ""; }; + 171143FF255EAFCE92AFD7B2A773B2C7 /* Tasks.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Tasks.html; path = docs/Tasks.html; sourceTree = ""; }; + 17652CA43D0C7A8AE4BDEEF4CE134EAE /* UITabBarController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = UITabBarController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UITabBarController.html; sourceTree = ""; }; + 17DE011BF898A9DF81E945B7546201AE /* Additional Assemblies.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Additional Assemblies.html"; path = "docs/Additional Assemblies.html"; sourceTree = ""; }; + 1871DA99CC86F3DC013B7BE150857130 /* Dismissible.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Dismissible.html; path = docs/Protocols/Dismissible.html; sourceTree = ""; }; + 18EA8CD294BF81276A4CF1E9FC27304A /* CustomWindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = CustomWindowProvider.html; path = docs/Structs/CustomWindowProvider.html; sourceTree = ""; }; 1974DFD21D7D0B0FBF528625873C9393 /* StackIterator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StackIterator.swift; sourceTree = ""; }; - 19789C50E4C8F1A34F4410551C6D6142 /* StackIteratingFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StackIteratingFinder.html; path = docs/Protocols/StackIteratingFinder.html; sourceTree = ""; }; - 1A387D4A5E9E0DFA88A9F8C872BC4B77 /* ClassWithContextFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ClassWithContextFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ClassWithContextFinder.html; sourceTree = ""; }; - 1A3D9C719B3CF580D4E5F98DCF0A19A8 /* InterceptorResult.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InterceptorResult.html; path = docs/Enums/InterceptorResult.html; sourceTree = ""; }; + 19789C50E4C8F1A34F4410551C6D6142 /* StackIteratingFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = StackIteratingFinder.html; path = docs/Protocols/StackIteratingFinder.html; sourceTree = ""; }; + 1A387D4A5E9E0DFA88A9F8C872BC4B77 /* ClassWithContextFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ClassWithContextFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ClassWithContextFinder.html; sourceTree = ""; }; + 1A3D9C719B3CF580D4E5F98DCF0A19A8 /* InterceptorResult.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = InterceptorResult.html; path = docs/Enums/InterceptorResult.html; sourceTree = ""; }; 1AB8EE43049793FB4D4E69AEDDF957E1 /* TaskCollector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TaskCollector.swift; sourceTree = ""; }; - 1B2511608F24B9AF6D7D7E0B51DEAD6D /* Array.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Array.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/Array.html; sourceTree = ""; }; + 1B2511608F24B9AF6D7D7E0B51DEAD6D /* Array.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Array.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/Array.html; sourceTree = ""; }; 1B35AE206B3FA4E9651AF24CDA4FF3D8 /* PostRoutingTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PostRoutingTask.swift; path = RouteComposer/Classes/PostRoutingTask.swift; sourceTree = ""; }; 1C7BB8FC6B77E699EA8CE5843FC09FE5 /* Pods-RouteComposer_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-RouteComposer_Example-dummy.m"; sourceTree = ""; }; - 1CAAC0BE2074E35F2CF8F117E0DC5519 /* ActionConnectingAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ActionConnectingAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ActionConnectingAssembly.html; sourceTree = ""; }; - 1D1B65CCD0F703925F4B5B92B3B8884A /* Extras.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Extras.html; path = docs/Extras.html; sourceTree = ""; }; - 1F04D9477B1037A7193842E98580E23D /* DismissibleWithRuntimeStorage.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DismissibleWithRuntimeStorage.html; path = docs/Protocols/DismissibleWithRuntimeStorage.html; sourceTree = ""; }; - 20A67EAD21E6F3CCF85566D5DB34FAAB /* ContainerAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContainerAction.html; sourceTree = ""; }; - 21420145D0F6106B59250EED87558229 /* ContainerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContainerFactory.html; sourceTree = ""; }; - 226EF41FB6965FC45C1B0897607910FF /* NavigationControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NavigationControllerFactory.html; path = docs/Structs/NavigationControllerFactory.html; sourceTree = ""; }; + 1CAAC0BE2074E35F2CF8F117E0DC5519 /* ActionConnectingAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ActionConnectingAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ActionConnectingAssembly.html; sourceTree = ""; }; + 1D1B65CCD0F703925F4B5B92B3B8884A /* Extras.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Extras.html; path = docs/Extras.html; sourceTree = ""; }; + 1F04D9477B1037A7193842E98580E23D /* DismissibleWithRuntimeStorage.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = DismissibleWithRuntimeStorage.html; path = docs/Protocols/DismissibleWithRuntimeStorage.html; sourceTree = ""; }; + 20A67EAD21E6F3CCF85566D5DB34FAAB /* ContainerAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContainerAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContainerAction.html; sourceTree = ""; }; + 21420145D0F6106B59250EED87558229 /* ContainerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContainerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContainerFactory.html; sourceTree = ""; }; + 226EF41FB6965FC45C1B0897607910FF /* NavigationControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = NavigationControllerFactory.html; path = docs/Structs/NavigationControllerFactory.html; sourceTree = ""; }; 22DF42B1E26F71346382619AE439C848 /* SplitControllerFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SplitControllerFactory.swift; sourceTree = ""; }; - 22E6B4C087313CDA84D3F894E940E03E /* TabBarControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = TabBarControllerActions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/TabBarControllerActions.html; sourceTree = ""; }; - 230F97C827A439357021A44BF3D43308 /* TabBarControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = TabBarControllerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/TabBarControllerFactory.html; sourceTree = ""; }; - 2355A10F272362BB59D3A9AD23E72D7E /* SimpleContainerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SimpleContainerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/SimpleContainerFactory.html; sourceTree = ""; }; - 239CB47CD0A39C8EA2C79E03DE5BF4AD /* FinderFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = FinderFactory.html; path = docs/Structs/FinderFactory.html; sourceTree = ""; }; - 2471E08C6130B2E01508E764FE932BE3 /* SplitControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SplitControllerStep.html; path = docs/Classes/SplitControllerStep.html; sourceTree = ""; }; - 25511E0D6B711EC66BAEF167730A4B02 /* UIViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UIViewController.html; path = docs/Extensions/UIViewController.html; sourceTree = ""; }; + 22E6B4C087313CDA84D3F894E940E03E /* TabBarControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = TabBarControllerActions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/TabBarControllerActions.html; sourceTree = ""; }; + 230F97C827A439357021A44BF3D43308 /* TabBarControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = TabBarControllerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/TabBarControllerFactory.html; sourceTree = ""; }; + 2355A10F272362BB59D3A9AD23E72D7E /* SimpleContainerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SimpleContainerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/SimpleContainerFactory.html; sourceTree = ""; }; + 239CB47CD0A39C8EA2C79E03DE5BF4AD /* FinderFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = FinderFactory.html; path = docs/Structs/FinderFactory.html; sourceTree = ""; }; + 2471E08C6130B2E01508E764FE932BE3 /* SplitControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SplitControllerStep.html; path = docs/Classes/SplitControllerStep.html; sourceTree = ""; }; + 25511E0D6B711EC66BAEF167730A4B02 /* UIViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = UIViewController.html; path = docs/Extensions/UIViewController.html; sourceTree = ""; }; 26F301B856AA06C8E0E6D0B2104151E3 /* StepAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StepAssembly.swift; sourceTree = ""; }; 26FF9CFEE6316023E8362C8D23AB1702 /* Logger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; - 275B590D7C79AB0B825335D66D6B75BC /* Finder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Finder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Finder.html; sourceTree = ""; }; + 275B590D7C79AB0B825335D66D6B75BC /* Finder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Finder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Finder.html; sourceTree = ""; }; 28C5DABC229D49A709B9F77EC7912974 /* WindowProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WindowProvider.swift; sourceTree = ""; }; - 28D36701AF3A49ABE7D2BE0F87025E1C /* DismissibleWithRuntimeStorage.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DismissibleWithRuntimeStorage.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/DismissibleWithRuntimeStorage.html; sourceTree = ""; }; + 28D36701AF3A49ABE7D2BE0F87025E1C /* DismissibleWithRuntimeStorage.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = DismissibleWithRuntimeStorage.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/DismissibleWithRuntimeStorage.html; sourceTree = ""; }; 2967570375C7B1960BCD8DE869FE62FF /* MainThreadChecking.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MainThreadChecking.swift; sourceTree = ""; }; 2A3CF8EC8305CA805FECD25412CC9A55 /* NilEntity.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NilEntity.swift; sourceTree = ""; }; - 2AC4ABFF99832C4480DD224A239F8C44 /* docSet.dsidx */ = {isa = PBXFileReference; includeInIndex = 1; name = docSet.dsidx; path = docs/docsets/RouteComposer.docset/Contents/Resources/docSet.dsidx; sourceTree = ""; }; - 2B7AB38FA6FDE7E5B610198E9B8DE792 /* Dismissible.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Dismissible.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Dismissible.html; sourceTree = ""; }; - 2D187107877E7159A1D5605696D2EAD2 /* RouteComposer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = RouteComposer.framework; path = RouteComposer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2AC4ABFF99832C4480DD224A239F8C44 /* docSet.dsidx */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file; name = docSet.dsidx; path = docs/docsets/RouteComposer.docset/Contents/Resources/docSet.dsidx; sourceTree = ""; }; + 2B7AB38FA6FDE7E5B610198E9B8DE792 /* Dismissible.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Dismissible.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Dismissible.html; sourceTree = ""; }; + 2D187107877E7159A1D5605696D2EAD2 /* RouteComposer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RouteComposer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2D5524F0D91D2B610E55890EBF5E9A7A /* DefaultRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DefaultRouter.swift; sourceTree = ""; }; - 2E56569F3582D71040F48616F6123742 /* NilFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NilFactory.html; path = docs/Structs/NilFactory.html; sourceTree = ""; }; + 2E56569F3582D71040F48616F6123742 /* NilFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = NilFactory.html; path = docs/Structs/NilFactory.html; sourceTree = ""; }; 2E9082E75314F36C36B4C41DB09C493E /* carat.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = carat.png; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/img/carat.png; sourceTree = ""; }; - 2F6F76A7C949060E83C64AD4EFAC728F /* AbstractAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = AbstractAction.html; path = docs/Protocols/AbstractAction.html; sourceTree = ""; }; + 2F6F76A7C949060E83C64AD4EFAC728F /* AbstractAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = AbstractAction.html; path = docs/Protocols/AbstractAction.html; sourceTree = ""; }; 2F78CFA667B5CA348274F92F625CD1AC /* ContextAccepting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContextAccepting.swift; sourceTree = ""; }; - 2FB227C87DE5BE0489AB63810F5018B2 /* LogMessage.html */ = {isa = PBXFileReference; includeInIndex = 1; name = LogMessage.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/LogMessage.html; sourceTree = ""; }; + 2FB227C87DE5BE0489AB63810F5018B2 /* LogMessage.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = LogMessage.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/LogMessage.html; sourceTree = ""; }; 3054456717875EEDD8BB574A5C193A43 /* Action.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Action.swift; path = RouteComposer/Classes/Action.swift; sourceTree = ""; }; 327423F5710A20F41E9B81B25270DAE7 /* InterceptableStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = InterceptableStep.swift; sourceTree = ""; }; 338505195AB5ACDC06D7C5FF0C2D51BB /* Pods-RouteComposer_Example-RouteComposer_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-RouteComposer_Example-RouteComposer_Tests-Info.plist"; sourceTree = ""; }; - 3386F7C079149FE9198CD978997E229A /* RoutingInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; name = RoutingInterceptor.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/RoutingInterceptor.html; sourceTree = ""; }; + 3386F7C079149FE9198CD978997E229A /* RoutingInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = RoutingInterceptor.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/RoutingInterceptor.html; sourceTree = ""; }; 343E7AAFDE97E53A77B53AD2DE755B27 /* Pods-RouteComposer_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-RouteComposer_Example.debug.xcconfig"; sourceTree = ""; }; - 348464A023ACA3F57C7C8D4C3F7A7E7A /* Other Structs.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Structs.html"; path = "docs/Other Structs.html"; sourceTree = ""; }; - 352170C7E97085E20A67E23E9E775246 /* DefaultStackIterator.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DefaultStackIterator.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultStackIterator.html; sourceTree = ""; }; - 3650FCF777EFE7935A714FBA9F934E78 /* InlinePostTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InlinePostTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/InlinePostTask.html; sourceTree = ""; }; - 3692C6D698BD95DE7AFBF0C6B7115806 /* RoutingError.html */ = {isa = PBXFileReference; includeInIndex = 1; name = RoutingError.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/RoutingError.html; sourceTree = ""; }; + 348464A023ACA3F57C7C8D4C3F7A7E7A /* Other Structs.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Other Structs.html"; path = "docs/Other Structs.html"; sourceTree = ""; }; + 352170C7E97085E20A67E23E9E775246 /* DefaultStackIterator.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = DefaultStackIterator.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultStackIterator.html; sourceTree = ""; }; + 3650FCF777EFE7935A714FBA9F934E78 /* InlinePostTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = InlinePostTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/InlinePostTask.html; sourceTree = ""; }; + 3692C6D698BD95DE7AFBF0C6B7115806 /* RoutingError.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = RoutingError.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/RoutingError.html; sourceTree = ""; }; 36A1F4FCEA2AC115E7B20D6EABB416B7 /* RouteComposer.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = RouteComposer.xcconfig; sourceTree = ""; }; 36DDFF2C559F3BDED52ADBC3E19089A6 /* BaseEntitiesCollector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BaseEntitiesCollector.swift; sourceTree = ""; }; - 36E51C39FB48AFF3179608F30F8C08A1 /* SplitViewControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SplitViewControllerActions.html; path = docs/Structs/SplitViewControllerActions.html; sourceTree = ""; }; + 36E51C39FB48AFF3179608F30F8C08A1 /* SplitViewControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SplitViewControllerActions.html; path = docs/Structs/SplitViewControllerActions.html; sourceTree = ""; }; 37C015C72A6784C7AA378A05B5C7C0D1 /* Finder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Finder.swift; path = RouteComposer/Classes/Finder.swift; sourceTree = ""; }; 37E4D0DD91E49E912E6D39272C0FEE4A /* RouteComposer-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "RouteComposer-umbrella.h"; sourceTree = ""; }; 38BF51883660A638A9BBEAF2053E9628 /* NavigationControllerStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NavigationControllerStep.swift; sourceTree = ""; }; - 3920737F682DA55A0991190F9F592DA2 /* UIViewController's protocols.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "UIViewController's protocols.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/UIViewController's protocols.html"; sourceTree = ""; }; - 3926BF7760A144732E213A82D85377AC /* search.json */ = {isa = PBXFileReference; includeInIndex = 1; name = search.json; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/search.json; sourceTree = ""; }; + 3920737F682DA55A0991190F9F592DA2 /* UIViewController's protocols.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "UIViewController's protocols.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/UIViewController's protocols.html"; sourceTree = ""; }; + 3926BF7760A144732E213A82D85377AC /* search.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = search.json; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/search.json; sourceTree = ""; }; 399AF0A55C2D57255DC61B4A073CFB9A /* TabBarViewController+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TabBarViewController+Extension.swift"; sourceTree = ""; }; - 39BBF862FAB7B0E7B9ECB85EC2EE8077 /* ChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ChainAssembly.html; path = docs/Structs/ChainAssembly.html; sourceTree = ""; }; - 39BE899F6E7BE05521340C4C8B25C8E0 /* ClassNameFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ClassNameFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ClassNameFactory.html; sourceTree = ""; }; + 39BBF862FAB7B0E7B9ECB85EC2EE8077 /* ChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ChainAssembly.html; path = docs/Structs/ChainAssembly.html; sourceTree = ""; }; + 39BE899F6E7BE05521340C4C8B25C8E0 /* ClassNameFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ClassNameFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ClassNameFactory.html; sourceTree = ""; }; 3A5B1E92F1EEBA2222CC41558D72F394 /* ActionBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ActionBox.swift; sourceTree = ""; }; 3B0D3576D12878794F99F285DB9BC284 /* PresentingFinder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PresentingFinder.swift; sourceTree = ""; }; - 3BC058066575A42AD54EA60D9A1C06B7 /* highlight.css */ = {isa = PBXFileReference; includeInIndex = 1; name = highlight.css; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/css/highlight.css; sourceTree = ""; }; - 3CE21B8507B8F12E9A7CBFC96729563E /* InterceptorResult.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InterceptorResult.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/InterceptorResult.html; sourceTree = ""; }; + 3BC058066575A42AD54EA60D9A1C06B7 /* highlight.css */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.css; name = highlight.css; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/css/highlight.css; sourceTree = ""; }; + 3CE21B8507B8F12E9A7CBFC96729563E /* InterceptorResult.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = InterceptorResult.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/InterceptorResult.html; sourceTree = ""; }; 3F30A277FC85BE4227E2E712E9EC146E /* RouteComposer.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = RouteComposer.modulemap; sourceTree = ""; }; 405799D886300D02616E99F997BE054A /* ClassWithContextFinder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ClassWithContextFinder.swift; sourceTree = ""; }; - 40AAF7063A0CA1A59C15F41C3F9E52ED /* jazzy.css */ = {isa = PBXFileReference; includeInIndex = 1; name = jazzy.css; path = docs/css/jazzy.css; sourceTree = ""; }; + 40AAF7063A0CA1A59C15F41C3F9E52ED /* jazzy.css */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.css; name = jazzy.css; path = docs/css/jazzy.css; sourceTree = ""; }; 40CB39E715FBCDAA142E6513E126200A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 4182FFFF28E50D48B3FB7930C2EED347 /* SplitControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SplitControllerFactory.html; path = docs/Structs/SplitControllerFactory.html; sourceTree = ""; }; - 419CA270943BB3E62F1686301BAC80D9 /* index.html */ = {isa = PBXFileReference; includeInIndex = 1; name = index.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/index.html; sourceTree = ""; }; - 4387D7AD7168427F151415FE547C79D0 /* GeneralStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = GeneralStep.html; path = docs/Structs/GeneralStep.html; sourceTree = ""; }; + 4182FFFF28E50D48B3FB7930C2EED347 /* SplitControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SplitControllerFactory.html; path = docs/Structs/SplitControllerFactory.html; sourceTree = ""; }; + 419CA270943BB3E62F1686301BAC80D9 /* index.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = index.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/index.html; sourceTree = ""; }; + 4387D7AD7168427F151415FE547C79D0 /* GeneralStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = GeneralStep.html; path = docs/Structs/GeneralStep.html; sourceTree = ""; }; 442307C43F441DE24C6B1B228823D0D3 /* ContainerViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContainerViewController.swift; path = RouteComposer/Classes/ContainerViewController.swift; sourceTree = ""; }; - 444124204F3FE20EB632D067AE114DA3 /* Core Entities.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Core Entities.html"; path = "docs/Core Entities.html"; sourceTree = ""; }; - 447C0B6A59B9DD9E321891D3D5784AF5 /* SplitViewControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SplitViewControllerActions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SplitViewControllerActions.html; sourceTree = ""; }; - 4640582D65A47719BE8898EEF868CDD1 /* ContainerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerFactory.html; path = docs/Protocols/ContainerFactory.html; sourceTree = ""; }; - 46EE17826012E7C2D8D9B8E84B262901 /* RoutingInterceptable.html */ = {isa = PBXFileReference; includeInIndex = 1; name = RoutingInterceptable.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/RoutingInterceptable.html; sourceTree = ""; }; - 473FF375570BCD85C4F622C95D419AEB /* AbstractFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = AbstractFactory.html; path = docs/Protocols/AbstractFactory.html; sourceTree = ""; }; - 49719ACB4C2125A8D4D2103ADF204A3A /* jazzy.css */ = {isa = PBXFileReference; includeInIndex = 1; name = jazzy.css; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/css/jazzy.css; sourceTree = ""; }; - 4A78CE5CB88FD9595EDDAA84FF918304 /* LastStepInChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = LastStepInChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/LastStepInChainAssembly.html; sourceTree = ""; }; + 444124204F3FE20EB632D067AE114DA3 /* Core Entities.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Core Entities.html"; path = "docs/Core Entities.html"; sourceTree = ""; }; + 447C0B6A59B9DD9E321891D3D5784AF5 /* SplitViewControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SplitViewControllerActions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SplitViewControllerActions.html; sourceTree = ""; }; + 4640582D65A47719BE8898EEF868CDD1 /* ContainerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContainerFactory.html; path = docs/Protocols/ContainerFactory.html; sourceTree = ""; }; + 46EE17826012E7C2D8D9B8E84B262901 /* RoutingInterceptable.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = RoutingInterceptable.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/RoutingInterceptable.html; sourceTree = ""; }; + 473FF375570BCD85C4F622C95D419AEB /* AbstractFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = AbstractFactory.html; path = docs/Protocols/AbstractFactory.html; sourceTree = ""; }; + 49719ACB4C2125A8D4D2103ADF204A3A /* jazzy.css */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.css; name = jazzy.css; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/css/jazzy.css; sourceTree = ""; }; + 4A78CE5CB88FD9595EDDAA84FF918304 /* LastStepInChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = LastStepInChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/LastStepInChainAssembly.html; sourceTree = ""; }; 4A8B7E1EE8B65751D32FF698E1A4D672 /* Pods-RouteComposer_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-RouteComposer_Example-acknowledgements.markdown"; sourceTree = ""; }; - 4A9A298A2B86D357320EE850D332C619 /* badge.svg */ = {isa = PBXFileReference; includeInIndex = 1; name = badge.svg; path = docs/badge.svg; sourceTree = ""; }; - 4AD6920DBA828D3A9886AB7B1F389830 /* StepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StepAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/StepAssembly.html; sourceTree = ""; }; - 4C7862E398BE35CACFD7BE0433CAA487 /* GeneralStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = GeneralStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/GeneralStep.html; sourceTree = ""; }; - 4D5DD76ABEFAA000D3CA1F651C6ECB29 /* ContainerStepChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerStepChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ContainerStepChainAssembly.html; sourceTree = ""; }; - 4DF3C3502999BF798C30B84E4B4580E6 /* Other Extensions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Extensions.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Extensions.html"; sourceTree = ""; }; + 4A9A298A2B86D357320EE850D332C619 /* badge.svg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = badge.svg; path = docs/badge.svg; sourceTree = ""; }; + 4AD6920DBA828D3A9886AB7B1F389830 /* StepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = StepAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/StepAssembly.html; sourceTree = ""; }; + 4C7862E398BE35CACFD7BE0433CAA487 /* GeneralStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = GeneralStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/GeneralStep.html; sourceTree = ""; }; + 4D5DD76ABEFAA000D3CA1F651C6ECB29 /* ContainerStepChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContainerStepChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ContainerStepChainAssembly.html; sourceTree = ""; }; + 4DF3C3502999BF798C30B84E4B4580E6 /* Other Extensions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Other Extensions.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Extensions.html"; sourceTree = ""; }; 4FCFC6C731703BD30865DF5732800DD0 /* Pods-RouteComposer_Example-RouteComposer_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-RouteComposer_Example-RouteComposer_Tests-umbrella.h"; sourceTree = ""; }; 501441AB96558538FE376AB26E8D6F52 /* FinderBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FinderBox.swift; sourceTree = ""; }; 505AAA7FA78386207E26D99E96DC95CC /* CustomWindowProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CustomWindowProvider.swift; sourceTree = ""; }; 5092DA2EA6EBEC2A8098564E0DECCB20 /* SplitControllerStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SplitControllerStep.swift; sourceTree = ""; }; - 5171D5708304E5216EAC29203909B6FC /* CompleteFactoryAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = CompleteFactoryAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/CompleteFactoryAssembly.html; sourceTree = ""; }; - 519C8CC3791D3ED4A095A52017C8336E /* Router.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Router.html; path = docs/Protocols/Router.html; sourceTree = ""; }; + 5171D5708304E5216EAC29203909B6FC /* CompleteFactoryAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = CompleteFactoryAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/CompleteFactoryAssembly.html; sourceTree = ""; }; + 519C8CC3791D3ED4A095A52017C8336E /* Router.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Router.html; path = docs/Protocols/Router.html; sourceTree = ""; }; 520068F09197E8DD9F2E74252C5F0E33 /* TabBarControllerFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TabBarControllerFactory.swift; sourceTree = ""; }; - 529079BE82B3C079DE0B3372B5944AE1 /* SetAsMasterAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SetAsMasterAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SplitViewControllerActions/SetAsMasterAction.html; sourceTree = ""; }; - 52F787709693EC9AB13EFF0AC805330B /* DestinationStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DestinationStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DestinationStep.html; sourceTree = ""; }; + 529079BE82B3C079DE0B3372B5944AE1 /* SetAsMasterAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SetAsMasterAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SplitViewControllerActions/SetAsMasterAction.html; sourceTree = ""; }; + 52F787709693EC9AB13EFF0AC805330B /* DestinationStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = DestinationStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DestinationStep.html; sourceTree = ""; }; 533516216035BF0B7F9F2371327AB11D /* SwitcherStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SwitcherStep.swift; sourceTree = ""; }; - 5375BB2CF89E2E9C99B97DDACAA2AE4D /* undocumented.json */ = {isa = PBXFileReference; includeInIndex = 1; name = undocumented.json; path = docs/undocumented.json; sourceTree = ""; }; - 555F6FCD627F2142435AB33AC3CB4703 /* Logger.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Logger.html; path = docs/Protocols/Logger.html; sourceTree = ""; }; + 5375BB2CF89E2E9C99B97DDACAA2AE4D /* undocumented.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = undocumented.json; path = docs/undocumented.json; sourceTree = ""; }; + 555F6FCD627F2142435AB33AC3CB4703 /* Logger.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Logger.html; path = docs/Protocols/Logger.html; sourceTree = ""; }; 558CB5800EACEB5E6870A0421450AFA4 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = Info.plist; path = docs/docsets/RouteComposer.docset/Contents/Info.plist; sourceTree = ""; }; - 562335B194EE0BD366AFB8B6609EA739 /* XibFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = XibFactory.html; path = docs/Structs/XibFactory.html; sourceTree = ""; }; - 584F3843D2CBB3C437F5AE6F96DD9B77 /* DefaultLogger.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DefaultLogger.html; path = docs/Structs/DefaultLogger.html; sourceTree = ""; }; - 589944296D9AD126C742A416BBF2D0EC /* GenericStepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = GenericStepAssembly.html; path = docs/Classes/GenericStepAssembly.html; sourceTree = ""; }; - 58D4182108B67FDB04DDD49346D0F59F /* GeneralAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = GeneralAction.html; path = docs/Structs/GeneralAction.html; sourceTree = ""; }; - 58DC9AEEE20BEDF62E15842441A1CC2D /* ClassWithContextFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ClassWithContextFinder.html; path = docs/Structs/ClassWithContextFinder.html; sourceTree = ""; }; + 562335B194EE0BD366AFB8B6609EA739 /* XibFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = XibFactory.html; path = docs/Structs/XibFactory.html; sourceTree = ""; }; + 584F3843D2CBB3C437F5AE6F96DD9B77 /* DefaultLogger.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = DefaultLogger.html; path = docs/Structs/DefaultLogger.html; sourceTree = ""; }; + 589944296D9AD126C742A416BBF2D0EC /* GenericStepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = GenericStepAssembly.html; path = docs/Classes/GenericStepAssembly.html; sourceTree = ""; }; + 58D4182108B67FDB04DDD49346D0F59F /* GeneralAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = GeneralAction.html; path = docs/Structs/GeneralAction.html; sourceTree = ""; }; + 58DC9AEEE20BEDF62E15842441A1CC2D /* ClassWithContextFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ClassWithContextFinder.html; path = docs/Structs/ClassWithContextFinder.html; sourceTree = ""; }; 5A43E1BA0EAB7023F2AE2DBAF0BCC237 /* InstanceFinder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = InstanceFinder.swift; sourceTree = ""; }; - 5A5FE2232843AD971315833408D6EB41 /* AbstractFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = AbstractFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/AbstractFactory.html; sourceTree = ""; }; - 5A64E8D4C81AB17C9214D3F8F01972A1 /* Factory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Factory.html; path = docs/Protocols/Factory.html; sourceTree = ""; }; - 5AE37AAB406DAB6100821BD74520B9AA /* Additional Assemblies.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Additional Assemblies.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Additional Assemblies.html"; sourceTree = ""; }; - 5AED00E031D7286E53FEB779EBE9914B /* LogLevel.html */ = {isa = PBXFileReference; includeInIndex = 1; name = LogLevel.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultLogger/LogLevel.html; sourceTree = ""; }; + 5A5FE2232843AD971315833408D6EB41 /* AbstractFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = AbstractFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/AbstractFactory.html; sourceTree = ""; }; + 5A64E8D4C81AB17C9214D3F8F01972A1 /* Factory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Factory.html; path = docs/Protocols/Factory.html; sourceTree = ""; }; + 5AE37AAB406DAB6100821BD74520B9AA /* Additional Assemblies.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Additional Assemblies.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Additional Assemblies.html"; sourceTree = ""; }; + 5AED00E031D7286E53FEB779EBE9914B /* LogLevel.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = LogLevel.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultLogger/LogLevel.html; sourceTree = ""; }; 5B99BBC14EE9923A82AB721892C88546 /* UIWindow+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UIWindow+Extension.swift"; sourceTree = ""; }; 5C3ECCAE50F7487971449710EBAA4811 /* SplitViewController+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "SplitViewController+Extension.swift"; sourceTree = ""; }; - 5D90466A072349A21B92E728D15A7930 /* RoutingInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; name = RoutingInterceptor.html; path = docs/Protocols/RoutingInterceptor.html; sourceTree = ""; }; - 5DAB8748145A85C6437F277AA5282E6B /* Assemblies.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Assemblies.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Assemblies.html; sourceTree = ""; }; + 5D90466A072349A21B92E728D15A7930 /* RoutingInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = RoutingInterceptor.html; path = docs/Protocols/RoutingInterceptor.html; sourceTree = ""; }; + 5DAB8748145A85C6437F277AA5282E6B /* Assemblies.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Assemblies.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Assemblies.html; sourceTree = ""; }; 5E3782AA532D1755D86F72750908BFA9 /* GeneralStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GeneralStep.swift; sourceTree = ""; }; 5E3819EB22816CC8E10AF7C83D924AB2 /* InterceptableStepAssembling.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = InterceptableStepAssembling.swift; sourceTree = ""; }; - 5F2CF55C58C7A82A823FC3A4E9CD009D /* SwitchAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SwitchAssembly.html; path = docs/Classes/SwitchAssembly.html; sourceTree = ""; }; - 5FD3F7490356C9B486CF1E54CA563176 /* Finders.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Finders.html; path = docs/Finders.html; sourceTree = ""; }; - 6048F702AB5996DD03943FBFD38972E4 /* StartingPoint.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StartingPoint.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultStackIterator/StartingPoint.html; sourceTree = ""; }; + 5F2CF55C58C7A82A823FC3A4E9CD009D /* SwitchAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SwitchAssembly.html; path = docs/Classes/SwitchAssembly.html; sourceTree = ""; }; + 5FD3F7490356C9B486CF1E54CA563176 /* Finders.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Finders.html; path = docs/Finders.html; sourceTree = ""; }; + 6048F702AB5996DD03943FBFD38972E4 /* StartingPoint.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = StartingPoint.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultStackIterator/StartingPoint.html; sourceTree = ""; }; 607E8E7BFCE511CB78939E8D7CB8865E /* ChainAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ChainAssembly.swift; sourceTree = ""; }; 60CAC3E2081552FE29ABFBEA8989C8DE /* ChainableStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ChainableStep.swift; sourceTree = ""; }; - 613A52B6E8E59CFB9CB0B811C0A7781E /* index.html */ = {isa = PBXFileReference; includeInIndex = 1; name = index.html; path = docs/index.html; sourceTree = ""; }; - 638DB341A4CA1565C52E1B03CFDA9E53 /* Finders.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Finders.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Finders.html; sourceTree = ""; }; - 638E358003D69EB83E0124C566C56884 /* examples.html */ = {isa = PBXFileReference; includeInIndex = 1; name = examples.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/examples.html; sourceTree = ""; }; + 613A52B6E8E59CFB9CB0B811C0A7781E /* index.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = index.html; path = docs/index.html; sourceTree = ""; }; + 638DB341A4CA1565C52E1B03CFDA9E53 /* Finders.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Finders.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Finders.html; sourceTree = ""; }; + 638E358003D69EB83E0124C566C56884 /* examples.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = examples.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/examples.html; sourceTree = ""; }; 6555A6CFF08C36B7F5386396CAC27AB7 /* Pods-RouteComposer_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-RouteComposer_Example-acknowledgements.plist"; sourceTree = ""; }; - 65CDBA23B8E7AC07D76F2E48EC5B57A1 /* LastStepInChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = LastStepInChainAssembly.html; path = docs/Structs/LastStepInChainAssembly.html; sourceTree = ""; }; + 65CDBA23B8E7AC07D76F2E48EC5B57A1 /* LastStepInChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = LastStepInChainAssembly.html; path = docs/Structs/LastStepInChainAssembly.html; sourceTree = ""; }; 65D052ADFF4A81AE3C05EA6728BFAA0F /* Pods-RouteComposer_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-RouteComposer_Example.release.xcconfig"; sourceTree = ""; }; - 6623FCC048C35BCDE6326060AE76B00C /* NilFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NilFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NilFinder.html; sourceTree = ""; }; - 6650B93533BD9551620525DFDA9D941E /* ContextChecking.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContextChecking.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContextChecking.html; sourceTree = ""; }; + 6623FCC048C35BCDE6326060AE76B00C /* NilFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = NilFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NilFinder.html; sourceTree = ""; }; + 6650B93533BD9551620525DFDA9D941E /* ContextChecking.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContextChecking.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContextChecking.html; sourceTree = ""; }; 67808378EE247385D615A3876441C130 /* gh.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = gh.png; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/img/gh.png; sourceTree = ""; }; - 67F12432D8829973B54D3E157ED817A6 /* Resulting Enums.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Resulting Enums.html"; path = "docs/Resulting Enums.html"; sourceTree = ""; }; + 67F12432D8829973B54D3E157ED817A6 /* Resulting Enums.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Resulting Enums.html"; path = "docs/Resulting Enums.html"; sourceTree = ""; }; 693636867E0B20561B988D721F94B6B9 /* UINavigationController+Action.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Action.swift"; sourceTree = ""; }; 69769752A61D722233509777E58B1743 /* DefaultRouter+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "DefaultRouter+Extension.swift"; sourceTree = ""; }; 6A1A43B3D0D34DCD77ED37541D367DD1 /* InterceptorResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = InterceptorResult.swift; path = RouteComposer/Classes/InterceptorResult.swift; sourceTree = ""; }; - 6C023FDCCD9C1EC53BC3299E6D59CF06 /* SingleContainerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SingleContainerStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SingleContainerStep.html; sourceTree = ""; }; - 6CD15592EE471F7509BEBD1B9828C9B3 /* Assemblies.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Assemblies.html; path = docs/Assemblies.html; sourceTree = ""; }; - 6D64CBF58C08E4F9F985C5A66B90B686 /* NilFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NilFinder.html; path = docs/Structs/NilFinder.html; sourceTree = ""; }; + 6C023FDCCD9C1EC53BC3299E6D59CF06 /* SingleContainerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SingleContainerStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SingleContainerStep.html; sourceTree = ""; }; + 6CD15592EE471F7509BEBD1B9828C9B3 /* Assemblies.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Assemblies.html; path = docs/Assemblies.html; sourceTree = ""; }; + 6D64CBF58C08E4F9F985C5A66B90B686 /* NilFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = NilFinder.html; path = docs/Structs/NilFinder.html; sourceTree = ""; }; 6DF958E0814AED8492B86970511F4371 /* SimpleContainerFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SimpleContainerFactory.swift; sourceTree = ""; }; 6E41BE4B9907AE16275F20DD6F795AF5 /* AbstractFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AbstractFactory.swift; path = RouteComposer/Classes/AbstractFactory.swift; sourceTree = ""; }; 6E60FC914A1DECDEEF920BEC4DDBEF9F /* DismissalMethodProvidingContextTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DismissalMethodProvidingContextTask.swift; sourceTree = ""; }; 6E9C9512AE194707FC309A27F9D96D16 /* ContainerStepChainAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContainerStepChainAssembly.swift; sourceTree = ""; }; - 6EA362C3815CD13842AB963B4E153551 /* Context.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Context.html; path = docs/Enums/RoutingError/Context.html; sourceTree = ""; }; + 6EA362C3815CD13842AB963B4E153551 /* Context.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Context.html; path = docs/Enums/RoutingError/Context.html; sourceTree = ""; }; 6EC40AC055C98EB5B16288882AA9D847 /* ContainerActionBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContainerActionBox.swift; sourceTree = ""; }; - 6F4F26CE275A7602D2EABB604DED9EF5 /* FinderFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = FinderFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/FinderFactory.html; sourceTree = ""; }; - 7078FFF4424462C394E9E64414DDA32E /* PushToDetailsAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PushToDetailsAction.html; path = docs/Structs/SplitViewControllerActions/PushToDetailsAction.html; sourceTree = ""; }; - 708289F9A35436A9168FBAD73D33C7B8 /* ContainerViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerViewController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContainerViewController.html; sourceTree = ""; }; - 71FC4B34D5695FC9646D3CCCA9B84F26 /* NavigationControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NavigationControllerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerFactory.html; sourceTree = ""; }; + 6F4F26CE275A7602D2EABB604DED9EF5 /* FinderFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = FinderFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/FinderFactory.html; sourceTree = ""; }; + 7078FFF4424462C394E9E64414DDA32E /* PushToDetailsAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = PushToDetailsAction.html; path = docs/Structs/SplitViewControllerActions/PushToDetailsAction.html; sourceTree = ""; }; + 708289F9A35436A9168FBAD73D33C7B8 /* ContainerViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContainerViewController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ContainerViewController.html; sourceTree = ""; }; + 71FC4B34D5695FC9646D3CCCA9B84F26 /* NavigationControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = NavigationControllerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerFactory.html; sourceTree = ""; }; 72D1D6B4F165BEBE447C0223DB6674C0 /* Pods-RouteComposer_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-RouteComposer_Example.modulemap"; sourceTree = ""; }; - 731D7F12ED34A27A5F6B57792C4D7318 /* SingleNavigationRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SingleNavigationRouter.html; path = docs/Structs/SingleNavigationRouter.html; sourceTree = ""; }; - 7413DF4080D7EE28811F5D554544AC62 /* ContainerStepChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerStepChainAssembly.html; path = docs/Structs/ContainerStepChainAssembly.html; sourceTree = ""; }; + 731D7F12ED34A27A5F6B57792C4D7318 /* SingleNavigationRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SingleNavigationRouter.html; path = docs/Structs/SingleNavigationRouter.html; sourceTree = ""; }; + 7413DF4080D7EE28811F5D554544AC62 /* ContainerStepChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContainerStepChainAssembly.html; path = docs/Structs/ContainerStepChainAssembly.html; sourceTree = ""; }; 74F65AB7E4905EEAC91C85FB6E7F9957 /* AnyFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyFactory.swift; sourceTree = ""; }; 74FFEEA6B94A2545EFE23D5614C50064 /* RoutingResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RoutingResult.swift; path = RouteComposer/Classes/RoutingResult.swift; sourceTree = ""; }; 7695321D70A6893C9051F6A9FA70568A /* SingleContainerStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SingleContainerStep.swift; sourceTree = ""; }; - 7720B6D880D7FC48DF8B6437A06BE726 /* LogMessage.html */ = {isa = PBXFileReference; includeInIndex = 1; name = LogMessage.html; path = docs/Enums/LogMessage.html; sourceTree = ""; }; - 772BFC1BA3E52CEFF125B14BFC8C925D /* NavigationControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NavigationControllerStep.html; path = docs/Classes/NavigationControllerStep.html; sourceTree = ""; }; + 7720B6D880D7FC48DF8B6437A06BE726 /* LogMessage.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = LogMessage.html; path = docs/Enums/LogMessage.html; sourceTree = ""; }; + 772BFC1BA3E52CEFF125B14BFC8C925D /* NavigationControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = NavigationControllerStep.html; path = docs/Classes/NavigationControllerStep.html; sourceTree = ""; }; 78073F294062AE294CAFA161638F2424 /* ActionConnectingAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ActionConnectingAssembly.swift; sourceTree = ""; }; 79ADA5CDAD00A806EE8427698A94C7D6 /* UIViewController+Action.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UIViewController+Action.swift"; sourceTree = ""; }; - 7C3A289D2DFE9B1DBAC6ADF3B3C91C2F /* ChildCoordinator.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ChildCoordinator.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ChildCoordinator.html; sourceTree = ""; }; - 7CA5D4E88E57803A1A3261F2559DCC7E /* InterceptableRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InterceptableRouter.html; path = docs/Protocols/InterceptableRouter.html; sourceTree = ""; }; - 7D6248094D6AAF156F945CE5A7621589 /* StepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StepAssembly.html; path = docs/Classes/StepAssembly.html; sourceTree = ""; }; + 7C3A289D2DFE9B1DBAC6ADF3B3C91C2F /* ChildCoordinator.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ChildCoordinator.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ChildCoordinator.html; sourceTree = ""; }; + 7CA5D4E88E57803A1A3261F2559DCC7E /* InterceptableRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = InterceptableRouter.html; path = docs/Protocols/InterceptableRouter.html; sourceTree = ""; }; + 7D6248094D6AAF156F945CE5A7621589 /* StepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = StepAssembly.html; path = docs/Classes/StepAssembly.html; sourceTree = ""; }; 7E82F2960F4530024C161BDE95A89DFA /* LastStepInChainAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LastStepInChainAssembly.swift; sourceTree = ""; }; - 7F8745524D90562C9419119E0600EE8C /* jazzy.js */ = {isa = PBXFileReference; includeInIndex = 1; name = jazzy.js; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/js/jazzy.js; sourceTree = ""; }; + 7F8745524D90562C9419119E0600EE8C /* jazzy.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jazzy.js; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/js/jazzy.js; sourceTree = ""; }; 7FA6A2AA469FBCDC458B47A7C195BECF /* SearchOptions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SearchOptions.swift; path = RouteComposer/Classes/SearchOptions.swift; sourceTree = ""; }; 80868B2AFBC44B75DA8281140FB763C3 /* ContainerFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContainerFactory.swift; path = RouteComposer/Classes/ContainerFactory.swift; sourceTree = ""; }; - 80E391DADE8E631040A5CC4D65CCBC15 /* RouteComposer.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = RouteComposer.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 80E391DADE8E631040A5CC4D65CCBC15 /* RouteComposer.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = RouteComposer.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 81813567A553D3AB328EFED0EB9880FA /* AnyPostRoutingTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyPostRoutingTask.swift; sourceTree = ""; }; - 82410A410221CB1C62B1FDCF23403D9C /* Core Entities.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Core Entities.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Core Entities.html"; sourceTree = ""; }; - 829AE5E06BFEBB6A68C6010A7FA1C4BF /* SplitControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SplitControllerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SplitControllerFactory.html; sourceTree = ""; }; - 835CE96F0D02F8A4309F20E8B1906EF3 /* SearchOptions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SearchOptions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SearchOptions.html; sourceTree = ""; }; - 84D389797F0BB4C9245866D18C13D829 /* Context.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Context.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/RoutingError/Context.html; sourceTree = ""; }; + 82410A410221CB1C62B1FDCF23403D9C /* Core Entities.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Core Entities.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Core Entities.html"; sourceTree = ""; }; + 829AE5E06BFEBB6A68C6010A7FA1C4BF /* SplitControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SplitControllerFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SplitControllerFactory.html; sourceTree = ""; }; + 835CE96F0D02F8A4309F20E8B1906EF3 /* SearchOptions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SearchOptions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/SearchOptions.html; sourceTree = ""; }; + 84D389797F0BB4C9245866D18C13D829 /* Context.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Context.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/RoutingError/Context.html; sourceTree = ""; }; 860382B57E4F631E14EBD32DEDA4DB72 /* Pods-RouteComposer_Example-RouteComposer_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-RouteComposer_Example-RouteComposer_Tests.debug.xcconfig"; sourceTree = ""; }; 86CB6CA80AE3011435A5E0918CFF8793 /* AnyRoutingInterceptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyRoutingInterceptor.swift; sourceTree = ""; }; - 86FDFFE3C442F494CD99D0606AF9AB62 /* ContainerViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerViewController.html; path = docs/Protocols/ContainerViewController.html; sourceTree = ""; }; - 88AE1D09B564683EFB7D562B715CC2C7 /* InlineContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InlineContextTask.html; path = docs/Structs/InlineContextTask.html; sourceTree = ""; }; - 891C471943A2A1E7AA0270EA40C879F7 /* StackIterator.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StackIterator.html; path = docs/Protocols/StackIterator.html; sourceTree = ""; }; - 899C5A9628A223C458CE379D029C9B61 /* ViewControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ViewControllerActions.html; path = docs/Structs/ViewControllerActions.html; sourceTree = ""; }; + 86FDFFE3C442F494CD99D0606AF9AB62 /* ContainerViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContainerViewController.html; path = docs/Protocols/ContainerViewController.html; sourceTree = ""; }; + 88AE1D09B564683EFB7D562B715CC2C7 /* InlineContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = InlineContextTask.html; path = docs/Structs/InlineContextTask.html; sourceTree = ""; }; + 891C471943A2A1E7AA0270EA40C879F7 /* StackIterator.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = StackIterator.html; path = docs/Protocols/StackIterator.html; sourceTree = ""; }; + 899C5A9628A223C458CE379D029C9B61 /* ViewControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ViewControllerActions.html; path = docs/Structs/ViewControllerActions.html; sourceTree = ""; }; 89B4422091B4BEDD1C715D17F17CB9C4 /* RoutingStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RoutingStep.swift; sourceTree = ""; }; - 8A4B2D917F36382CAA948C80765F2DD0 /* Other Classes.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Classes.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Classes.html"; sourceTree = ""; }; + 8A4B2D917F36382CAA948C80765F2DD0 /* Other Classes.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Other Classes.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Classes.html"; sourceTree = ""; }; 8AB540FDC7F5B230E9D16C5A0C3AC3B2 /* ClassNameFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ClassNameFactory.swift; sourceTree = ""; }; - 8AE42823C2691AB8E7B76861867A3325 /* ActionConnectingAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ActionConnectingAssembly.html; path = docs/Structs/ActionConnectingAssembly.html; sourceTree = ""; }; - 8BE8FB828CE7B6A2129D761F61861606 /* PresentingFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PresentingFinder.html; path = docs/Structs/PresentingFinder.html; sourceTree = ""; }; - 8C03C97DDD6D07DCAD162FE41AAC1FF6 /* Strategy.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Strategy.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationDelayingInterceptor/Strategy.html; sourceTree = ""; }; + 8AE42823C2691AB8E7B76861867A3325 /* ActionConnectingAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ActionConnectingAssembly.html; path = docs/Structs/ActionConnectingAssembly.html; sourceTree = ""; }; + 8BE8FB828CE7B6A2129D761F61861606 /* PresentingFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = PresentingFinder.html; path = docs/Structs/PresentingFinder.html; sourceTree = ""; }; + 8C03C97DDD6D07DCAD162FE41AAC1FF6 /* Strategy.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Strategy.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationDelayingInterceptor/Strategy.html; sourceTree = ""; }; 8E43304665A81ECFC474FB2E7779DD21 /* Array+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Array+Extension.swift"; sourceTree = ""; }; - 8F0F20CDE1CC1F209F09F824A6041B68 /* ClassNameFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ClassNameFactory.html; path = docs/Structs/ClassNameFactory.html; sourceTree = ""; }; + 8F0F20CDE1CC1F209F09F824A6041B68 /* ClassNameFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ClassNameFactory.html; path = docs/Structs/ClassNameFactory.html; sourceTree = ""; }; 90E0A10D03D82CC51FBAD825EBC10102 /* StoryboardFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StoryboardFactory.swift; sourceTree = ""; }; 90F88129F40F64AC978C0A6EC3295FFC /* Pods-RouteComposer_Example-RouteComposer_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-RouteComposer_Example-RouteComposer_Tests-dummy.m"; sourceTree = ""; }; - 92359D7FF551823FCB91094F5A4DF63D /* Array.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Array.html; path = docs/Extensions/Array.html; sourceTree = ""; }; - 93120D1B3A6FE6610C38A310BAAA24BB /* ChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ChainAssembly.html; sourceTree = ""; }; - 931EA51BDB290A7E86D1A4AD0A139BB2 /* TabBarControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = TabBarControllerStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/TabBarControllerStep.html; sourceTree = ""; }; + 92359D7FF551823FCB91094F5A4DF63D /* Array.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Array.html; path = docs/Extensions/Array.html; sourceTree = ""; }; + 93120D1B3A6FE6610C38A310BAAA24BB /* ChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ChainAssembly.html; sourceTree = ""; }; + 931EA51BDB290A7E86D1A4AD0A139BB2 /* TabBarControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = TabBarControllerStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/TabBarControllerStep.html; sourceTree = ""; }; 9383FAB12D7F2CA3CDE22B865DBB067B /* carat.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = carat.png; path = docs/img/carat.png; sourceTree = ""; }; - 93E677164C73C4FEBA2E0A269A80E1C6 /* UINavigationController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UINavigationController.html; path = docs/Extensions/UINavigationController.html; sourceTree = ""; }; + 93E677164C73C4FEBA2E0A269A80E1C6 /* UINavigationController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = UINavigationController.html; path = docs/Extensions/UINavigationController.html; sourceTree = ""; }; 93FF79ED112CF97AF510933B0C355EB5 /* ActionResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ActionResult.swift; path = RouteComposer/Classes/ActionResult.swift; sourceTree = ""; }; - 943CCD768910E138CF5E9EF640C75649 /* SingleNavigationLock.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SingleNavigationLock.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SingleNavigationLock.html; sourceTree = ""; }; - 94D44DF58E73A72C4A72E8D9625A885C /* ClassFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ClassFinder.html; path = docs/Structs/ClassFinder.html; sourceTree = ""; }; - 95942F1B09F1195116513D0DE8A814EA /* Factories.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Factories.html; path = docs/Factories.html; sourceTree = ""; }; - 95DAFF733EE12CE23AE236E4A80A1E14 /* ContainerStepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerStepAssembly.html; path = docs/Classes/ContainerStepAssembly.html; sourceTree = ""; }; - 96638CC3A2ED353E2E9599D5271C48AC /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + 943CCD768910E138CF5E9EF640C75649 /* SingleNavigationLock.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SingleNavigationLock.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SingleNavigationLock.html; sourceTree = ""; }; + 94D44DF58E73A72C4A72E8D9625A885C /* ClassFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ClassFinder.html; path = docs/Structs/ClassFinder.html; sourceTree = ""; }; + 95942F1B09F1195116513D0DE8A814EA /* Factories.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Factories.html; path = docs/Factories.html; sourceTree = ""; }; + 95DAFF733EE12CE23AE236E4A80A1E14 /* ContainerStepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContainerStepAssembly.html; path = docs/Classes/ContainerStepAssembly.html; sourceTree = ""; }; + 96638CC3A2ED353E2E9599D5271C48AC /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 9684BBA911AD3707D7293A38815E6D24 /* FactoryBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FactoryBox.swift; sourceTree = ""; }; 96DF5E76EC7B1A8D8A13C08B018C77F4 /* ContextTaskMultiplexer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContextTaskMultiplexer.swift; sourceTree = ""; }; 96F1F63B88FDC2F01E8BA2D586C0829A /* SwitchAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SwitchAssembly.swift; sourceTree = ""; }; - 97721284FBF02F8E76A273A1703F7B79 /* ContextSettingTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContextSettingTask.html; path = docs/Structs/ContextSettingTask.html; sourceTree = ""; }; + 97721284FBF02F8E76A273A1703F7B79 /* ContextSettingTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContextSettingTask.html; path = docs/Structs/ContextSettingTask.html; sourceTree = ""; }; 97C67B0B0391834DBA602BEE033B4F46 /* AnyContextTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyContextTask.swift; sourceTree = ""; }; - 9829CE2EA22A4167262C18B4AD9772D7 /* RoutingInterceptable.html */ = {isa = PBXFileReference; includeInIndex = 1; name = RoutingInterceptable.html; path = docs/Protocols/RoutingInterceptable.html; sourceTree = ""; }; - 9AC649ACFA93F1F74D8D9AF9D357246E /* Other Structs.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Structs.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Structs.html"; sourceTree = ""; }; - 9B5BAA3323F56000143BD5527AC00638 /* SingleNavigationLock.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SingleNavigationLock.html; path = docs/Classes/SingleNavigationLock.html; sourceTree = ""; }; + 9829CE2EA22A4167262C18B4AD9772D7 /* RoutingInterceptable.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = RoutingInterceptable.html; path = docs/Protocols/RoutingInterceptable.html; sourceTree = ""; }; + 9AC649ACFA93F1F74D8D9AF9D357246E /* Other Structs.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Other Structs.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Structs.html"; sourceTree = ""; }; + 9B5BAA3323F56000143BD5527AC00638 /* SingleNavigationLock.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SingleNavigationLock.html; path = docs/Classes/SingleNavigationLock.html; sourceTree = ""; }; 9BA4A291580BE3952D81A952ACD4A303 /* RoutingError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RoutingError.swift; path = RouteComposer/Classes/RoutingError.swift; sourceTree = ""; }; - 9D62AC38C1385A8E23AE36F2D5B43073 /* InlineContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InlineContextTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/InlineContextTask.html; sourceTree = ""; }; - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9E4CF8BD6FB3F732AE87E503168FCD03 /* SearchOptions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SearchOptions.html; path = docs/Structs/SearchOptions.html; sourceTree = ""; }; - 9F5688F5B00074ED6877D2C17C92E702 /* contributing.html */ = {isa = PBXFileReference; includeInIndex = 1; name = contributing.html; path = docs/contributing.html; sourceTree = ""; }; - 9FDE9FFC0466DD6B10804D5FB011A042 /* UIWindow.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UIWindow.html; path = docs/Extensions/UIWindow.html; sourceTree = ""; }; - A1565A304A80657F5356D992062FE358 /* StepChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StepChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/StepChainAssembly.html; sourceTree = ""; }; - A2704AB6B3298510E5E1BAF68B7755B4 /* PushReplacingLastAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PushReplacingLastAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerActions/PushReplacingLastAction.html; sourceTree = ""; }; - A2D14BF6B16C94A82E8C801F7CD843BF /* SingleStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SingleStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SingleStep.html; sourceTree = ""; }; - A372968F7435B9E0441468506EC4E0C8 /* PostRoutingTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PostRoutingTask.html; path = docs/Protocols/PostRoutingTask.html; sourceTree = ""; }; - A3CF5909BFE6FF9EA39D10261F720357 /* SingleStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SingleStep.html; path = docs/Classes/SingleStep.html; sourceTree = ""; }; - A4CCD8B00BEB053B8FB018E58798E265 /* ReplaceRootAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ReplaceRootAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ViewControllerActions/ReplaceRootAction.html; sourceTree = ""; }; + 9D62AC38C1385A8E23AE36F2D5B43073 /* InlineContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = InlineContextTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/InlineContextTask.html; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9E4CF8BD6FB3F732AE87E503168FCD03 /* SearchOptions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SearchOptions.html; path = docs/Structs/SearchOptions.html; sourceTree = ""; }; + 9F5688F5B00074ED6877D2C17C92E702 /* contributing.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = contributing.html; path = docs/contributing.html; sourceTree = ""; }; + 9FDE9FFC0466DD6B10804D5FB011A042 /* UIWindow.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = UIWindow.html; path = docs/Extensions/UIWindow.html; sourceTree = ""; }; + A1565A304A80657F5356D992062FE358 /* StepChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = StepChainAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/StepChainAssembly.html; sourceTree = ""; }; + A2704AB6B3298510E5E1BAF68B7755B4 /* PushReplacingLastAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = PushReplacingLastAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerActions/PushReplacingLastAction.html; sourceTree = ""; }; + A2D14BF6B16C94A82E8C801F7CD843BF /* SingleStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SingleStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SingleStep.html; sourceTree = ""; }; + A372968F7435B9E0441468506EC4E0C8 /* PostRoutingTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = PostRoutingTask.html; path = docs/Protocols/PostRoutingTask.html; sourceTree = ""; }; + A3CF5909BFE6FF9EA39D10261F720357 /* SingleStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SingleStep.html; path = docs/Classes/SingleStep.html; sourceTree = ""; }; + A4CCD8B00BEB053B8FB018E58798E265 /* ReplaceRootAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ReplaceRootAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ViewControllerActions/ReplaceRootAction.html; sourceTree = ""; }; A4F88BF5002DDAA7D34BF5791523FC59 /* ActionConnecting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ActionConnecting.swift; sourceTree = ""; }; - A60B1549C923F490573420764ECB9387 /* contributing.html */ = {isa = PBXFileReference; includeInIndex = 1; name = contributing.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/contributing.html; sourceTree = ""; }; - A634A02E578F48E94E11FB03C6B507E4 /* highlight.css */ = {isa = PBXFileReference; includeInIndex = 1; name = highlight.css; path = docs/css/highlight.css; sourceTree = ""; }; + A60B1549C923F490573420764ECB9387 /* contributing.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = contributing.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/contributing.html; sourceTree = ""; }; + A634A02E578F48E94E11FB03C6B507E4 /* highlight.css */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.css; name = highlight.css; path = docs/css/highlight.css; sourceTree = ""; }; A65C2B87018D9A3A8F802F74700C8C58 /* DelayedIntegrationFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DelayedIntegrationFactory.swift; sourceTree = ""; }; A7ABC41CEA8223F84C722003F74A6F2E /* AnyActionBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyActionBox.swift; sourceTree = ""; }; A7C9CB9612EAED2DE167E9B0E49BF085 /* gh.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = gh.png; path = docs/img/gh.png; sourceTree = ""; }; - A807575ECAF460F5FEAA660D467AA82A /* ReplaceRootAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ReplaceRootAction.html; path = docs/Structs/ViewControllerActions/ReplaceRootAction.html; sourceTree = ""; }; - A94B4919122F5BEB6C032D37975D9954 /* ContextAccepting.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContextAccepting.html; path = docs/Protocols/ContextAccepting.html; sourceTree = ""; }; - AB74F041B04925442328EADFBF4AAFB9 /* StartingPoint.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StartingPoint.html; path = docs/Structs/DefaultStackIterator/StartingPoint.html; sourceTree = ""; }; + A807575ECAF460F5FEAA660D467AA82A /* ReplaceRootAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ReplaceRootAction.html; path = docs/Structs/ViewControllerActions/ReplaceRootAction.html; sourceTree = ""; }; + A94B4919122F5BEB6C032D37975D9954 /* ContextAccepting.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContextAccepting.html; path = docs/Protocols/ContextAccepting.html; sourceTree = ""; }; + AB74F041B04925442328EADFBF4AAFB9 /* StartingPoint.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = StartingPoint.html; path = docs/Structs/DefaultStackIterator/StartingPoint.html; sourceTree = ""; }; ABF48AF49B6A61BDBFB255FB3BA6359A /* ContextSettingTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContextSettingTask.swift; sourceTree = ""; }; AC7946B169DCF29471B69BE15F3C7198 /* ChildCoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChildCoordinator.swift; path = RouteComposer/Classes/ChildCoordinator.swift; sourceTree = ""; }; AC7A6DE28AFEED4A8AEFBDA8A155B62D /* ContextTaskBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContextTaskBox.swift; sourceTree = ""; }; - AE4E98F8B39DE2CEA2A3D75323BC5FE7 /* UIViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UIViewController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UIViewController.html; sourceTree = ""; }; + AE4E98F8B39DE2CEA2A3D75323BC5FE7 /* UIViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = UIViewController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UIViewController.html; sourceTree = ""; }; AE5B955F04AADBF4F9AF82D35B61507B /* DestinationStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DestinationStep.swift; path = RouteComposer/Classes/DestinationStep.swift; sourceTree = ""; }; - AEDE41D7806971121E9D663982098E6B /* UISplitViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UISplitViewController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UISplitViewController.html; sourceTree = ""; }; - AEE4E64F58797153B747867BC747E175 /* RoutingResult.html */ = {isa = PBXFileReference; includeInIndex = 1; name = RoutingResult.html; path = docs/Enums/RoutingResult.html; sourceTree = ""; }; + AEDE41D7806971121E9D663982098E6B /* UISplitViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = UISplitViewController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UISplitViewController.html; sourceTree = ""; }; + AEE4E64F58797153B747867BC747E175 /* RoutingResult.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = RoutingResult.html; path = docs/Enums/RoutingResult.html; sourceTree = ""; }; AF6F5F5A1E2EF4048F07025A72E82B29 /* NilFinder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NilFinder.swift; sourceTree = ""; }; AF74C2FA93071184D81B82577A9B37B9 /* UISplitViewController+Action.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UISplitViewController+Action.swift"; sourceTree = ""; }; - AFD713C3E3AF0DA87031D8A405CC4DE8 /* PushAsRootAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PushAsRootAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerActions/PushAsRootAction.html; sourceTree = ""; }; + AFD713C3E3AF0DA87031D8A405CC4DE8 /* PushAsRootAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = PushAsRootAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerActions/PushAsRootAction.html; sourceTree = ""; }; AFDF04AE0F6D759B82AFD6850A056200 /* Pods-RouteComposer_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-RouteComposer_Example-umbrella.h"; sourceTree = ""; }; - B01B3FB1A18AF0F39B8F5361728D34D1 /* NavigationDelayingInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NavigationDelayingInterceptor.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationDelayingInterceptor.html; sourceTree = ""; }; - B11BA6C5F5D0495BEA02310CB9056647 /* ActionResult.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ActionResult.html; path = docs/Enums/ActionResult.html; sourceTree = ""; }; - B138AD6A47462D3F25DA3BA9301203AC /* ActionResult.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ActionResult.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/ActionResult.html; sourceTree = ""; }; - B16D6706AF3EC7964502327C5B22B931 /* TabBarControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = TabBarControllerStep.html; path = docs/Classes/TabBarControllerStep.html; sourceTree = ""; }; - B1CE65A0C38992DD85E474563FB5379B /* StackIterator.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StackIterator.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/StackIterator.html; sourceTree = ""; }; - B22434D6C74F26D750E385E2ED7C2EE1 /* NavigationControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NavigationControllerActions.html; path = docs/Structs/NavigationControllerActions.html; sourceTree = ""; }; - B29684A970E9D182788A7F2AA4B3ED59 /* examples.html */ = {isa = PBXFileReference; includeInIndex = 1; name = examples.html; path = docs/examples.html; sourceTree = ""; }; - B2A5F04ACBC6A03FFD97E5AC9997FEB8 /* jquery.min.js */ = {isa = PBXFileReference; includeInIndex = 1; name = jquery.min.js; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/js/jquery.min.js; sourceTree = ""; }; + B01B3FB1A18AF0F39B8F5361728D34D1 /* NavigationDelayingInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = NavigationDelayingInterceptor.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationDelayingInterceptor.html; sourceTree = ""; }; + B11BA6C5F5D0495BEA02310CB9056647 /* ActionResult.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ActionResult.html; path = docs/Enums/ActionResult.html; sourceTree = ""; }; + B138AD6A47462D3F25DA3BA9301203AC /* ActionResult.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ActionResult.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/ActionResult.html; sourceTree = ""; }; + B16D6706AF3EC7964502327C5B22B931 /* TabBarControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = TabBarControllerStep.html; path = docs/Classes/TabBarControllerStep.html; sourceTree = ""; }; + B1CE65A0C38992DD85E474563FB5379B /* StackIterator.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = StackIterator.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/StackIterator.html; sourceTree = ""; }; + B22434D6C74F26D750E385E2ED7C2EE1 /* NavigationControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = NavigationControllerActions.html; path = docs/Structs/NavigationControllerActions.html; sourceTree = ""; }; + B29684A970E9D182788A7F2AA4B3ED59 /* examples.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = examples.html; path = docs/examples.html; sourceTree = ""; }; + B2A5F04ACBC6A03FFD97E5AC9997FEB8 /* jquery.min.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jquery.min.js; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/js/jquery.min.js; sourceTree = ""; }; B2F7447F4F5E925EF97CA07DDB21EF3A /* dash.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = dash.png; path = docs/img/dash.png; sourceTree = ""; }; B32CB56684F10F3DEE09079AC71346FA /* Dismissible.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Dismissible.swift; sourceTree = ""; }; - B3381D44159A6AE0F5EEEC91192EC278 /* XibFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = XibFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/XibFactory.html; sourceTree = ""; }; - B4532017027A8E4F41377D279CAD5595 /* StepChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StepChainAssembly.html; path = docs/Structs/StepChainAssembly.html; sourceTree = ""; }; - B499414C87BC821DE4E7B272BD9A32D1 /* Router.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Router.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Router.html; sourceTree = ""; }; + B3381D44159A6AE0F5EEEC91192EC278 /* XibFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = XibFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/XibFactory.html; sourceTree = ""; }; + B4532017027A8E4F41377D279CAD5595 /* StepChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = StepChainAssembly.html; path = docs/Structs/StepChainAssembly.html; sourceTree = ""; }; + B499414C87BC821DE4E7B272BD9A32D1 /* Router.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Router.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Router.html; sourceTree = ""; }; B4BBA444A02B7098627D7526FC3839B1 /* KeyWindowProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = KeyWindowProvider.swift; sourceTree = ""; }; - B58AFA924A122B923398F40E7DE1A155 /* PushAsRootAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PushAsRootAction.html; path = docs/Structs/NavigationControllerActions/PushAsRootAction.html; sourceTree = ""; }; + B58AFA924A122B923398F40E7DE1A155 /* PushAsRootAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = PushAsRootAction.html; path = docs/Structs/NavigationControllerActions/PushAsRootAction.html; sourceTree = ""; }; B68D26A36D14ECF3267C374555C90CFE /* CompleteFactoryAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CompleteFactoryAssembly.swift; sourceTree = ""; }; B78CDA4C14F0EE65AD993846A1938AA1 /* Pods-RouteComposer_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-RouteComposer_Example-frameworks.sh"; sourceTree = ""; }; B805372353A282F47B716E0FA5058509 /* AnyAction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyAction.swift; sourceTree = ""; }; B8361011935D5AA667AAF782FDD2D8A9 /* ContainerFactoryBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContainerFactoryBox.swift; sourceTree = ""; }; B998708092DC44730F16CA81AB757E47 /* PostRoutingTaskBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PostRoutingTaskBox.swift; sourceTree = ""; }; - B9B04E4DD1CB0DA3BF2F21193620ECD6 /* TabBarControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = TabBarControllerFactory.html; path = docs/Structs/TabBarControllerFactory.html; sourceTree = ""; }; - BA9DC6845187971257E4677C0C54ADCA /* Tasks.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Tasks.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Tasks.html; sourceTree = ""; }; - BC648593EFF221FC7C4150879A3100BD /* KeyWindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; name = KeyWindowProvider.html; path = docs/Structs/KeyWindowProvider.html; sourceTree = ""; }; - BEC4D6AC8F677DBADB948E31710F8025 /* Other Extensions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Extensions.html"; path = "docs/Other Extensions.html"; sourceTree = ""; }; + B9B04E4DD1CB0DA3BF2F21193620ECD6 /* TabBarControllerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = TabBarControllerFactory.html; path = docs/Structs/TabBarControllerFactory.html; sourceTree = ""; }; + BA9DC6845187971257E4677C0C54ADCA /* Tasks.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Tasks.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Tasks.html; sourceTree = ""; }; + BC648593EFF221FC7C4150879A3100BD /* KeyWindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = KeyWindowProvider.html; path = docs/Structs/KeyWindowProvider.html; sourceTree = ""; }; + BEC4D6AC8F677DBADB948E31710F8025 /* Other Extensions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Other Extensions.html"; path = "docs/Other Extensions.html"; sourceTree = ""; }; BF368969053CF8B927A2A75F5880CE36 /* FinderFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FinderFactory.swift; sourceTree = ""; }; - BF525FC159DF6998C15690BCD508A8D5 /* Other Classes.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Classes.html"; path = "docs/Other Classes.html"; sourceTree = ""; }; + BF525FC159DF6998C15690BCD508A8D5 /* Other Classes.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Other Classes.html"; path = "docs/Other Classes.html"; sourceTree = ""; }; BF7397D51305C37299575ACB61D209B9 /* CompleteFactoryChainAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CompleteFactoryChainAssembly.swift; sourceTree = ""; }; - BFEF101F6AFF513FD2DCD3EED918D5A5 /* DefaultStackIterator.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DefaultStackIterator.html; path = docs/Structs/DefaultStackIterator.html; sourceTree = ""; }; + BFEF101F6AFF513FD2DCD3EED918D5A5 /* DefaultStackIterator.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = DefaultStackIterator.html; path = docs/Structs/DefaultStackIterator.html; sourceTree = ""; }; C08BEC8FFB40CB6D5BA911B93F192905 /* Factory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Factory.swift; path = RouteComposer/Classes/Factory.swift; sourceTree = ""; }; - C0CE7DC29A099DB9997E5F5FC23483DC /* jazzy.js */ = {isa = PBXFileReference; includeInIndex = 1; name = jazzy.js; path = docs/js/jazzy.js; sourceTree = ""; }; + C0CE7DC29A099DB9997E5F5FC23483DC /* jazzy.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jazzy.js; path = docs/js/jazzy.js; sourceTree = ""; }; C0D2BB862F079FBC5DEF176FFD2B31B9 /* ActionToStepIntegrator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ActionToStepIntegrator.swift; sourceTree = ""; }; - C15B449593DAB6CA426C4673D9EBE230 /* NavigationDelayingInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NavigationDelayingInterceptor.html; path = docs/Structs/NavigationDelayingInterceptor.html; sourceTree = ""; }; + C15B449593DAB6CA426C4673D9EBE230 /* NavigationDelayingInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = NavigationDelayingInterceptor.html; path = docs/Structs/NavigationDelayingInterceptor.html; sourceTree = ""; }; C37AF197324EF86C6085B0B080A66F31 /* Pods-RouteComposer_Example-RouteComposer_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-RouteComposer_Example-RouteComposer_Tests-frameworks.sh"; sourceTree = ""; }; C4DB5BC380A8D05968639AB8B3BF827E /* PerformableStepResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformableStepResult.swift; sourceTree = ""; }; - C540541A64CF09063A0F6AEACEDE4D71 /* Finder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Finder.html; path = docs/Protocols/Finder.html; sourceTree = ""; }; - C5A9B407D55FCD71AE762A5EFE9C1954 /* RouteComposer.tgz */ = {isa = PBXFileReference; includeInIndex = 1; name = RouteComposer.tgz; path = docs/docsets/RouteComposer.tgz; sourceTree = ""; }; + C540541A64CF09063A0F6AEACEDE4D71 /* Finder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Finder.html; path = docs/Protocols/Finder.html; sourceTree = ""; }; + C5A9B407D55FCD71AE762A5EFE9C1954 /* RouteComposer.tgz */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file; name = RouteComposer.tgz; path = docs/docsets/RouteComposer.tgz; sourceTree = ""; }; C5C79C228A8DEA22C52D5AED914A5342 /* Pods-RouteComposer_Example-RouteComposer_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-RouteComposer_Example-RouteComposer_Tests-acknowledgements.markdown"; sourceTree = ""; }; - C60B6D9D2AB04ADA17FD8C2B004A00FF /* NilFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NilFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NilFactory.html; sourceTree = ""; }; + C60B6D9D2AB04ADA17FD8C2B004A00FF /* NilFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = NilFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NilFactory.html; sourceTree = ""; }; C760223924CA7F8FE7937E7B8C11EF74 /* ContextChecking.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContextChecking.swift; sourceTree = ""; }; C7D9CAB3F31B27AB1D4F7B9A68B8B332 /* UITabBarController+Action.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UITabBarController+Action.swift"; sourceTree = ""; }; - C7EC77615DACD31AA2042BF7882BDEA1 /* ContainerStepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerStepAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/ContainerStepAssembly.html; sourceTree = ""; }; - C97FFC5D6B754A585DB838B9D279FC62 /* PushAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PushAction.html; path = docs/Structs/NavigationControllerActions/PushAction.html; sourceTree = ""; }; - C9AE8DB808F649CDA5F4120758A630CC /* NavigationControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NavigationControllerStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/NavigationControllerStep.html; sourceTree = ""; }; + C7EC77615DACD31AA2042BF7882BDEA1 /* ContainerStepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ContainerStepAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/ContainerStepAssembly.html; sourceTree = ""; }; + C97FFC5D6B754A585DB838B9D279FC62 /* PushAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = PushAction.html; path = docs/Structs/NavigationControllerActions/PushAction.html; sourceTree = ""; }; + C9AE8DB808F649CDA5F4120758A630CC /* NavigationControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = NavigationControllerStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/NavigationControllerStep.html; sourceTree = ""; }; CA29DE776B30456C081C43E0AD8402C2 /* SingleNavigationRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SingleNavigationRouter.swift; sourceTree = ""; }; - CAC5135C6DD033E215A4762ADFE5DFC7 /* Pods_RouteComposer_Example_RouteComposer_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_RouteComposer_Example_RouteComposer_Tests.framework; path = "Pods-RouteComposer_Example-RouteComposer_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - CAEB75B5743692F14542043ACD7659C4 /* CompleteFactoryAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = CompleteFactoryAssembly.html; path = docs/Classes/CompleteFactoryAssembly.html; sourceTree = ""; }; - CAF2B9DAE7973DA0642808432B1658EC /* NavigationControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; name = NavigationControllerActions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerActions.html; sourceTree = ""; }; - CB1C0397236C7C50682C1B5E8C6249FC /* SetAsMasterAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SetAsMasterAction.html; path = docs/Structs/SplitViewControllerActions/SetAsMasterAction.html; sourceTree = ""; }; + CAC5135C6DD033E215A4762ADFE5DFC7 /* Pods_RouteComposer_Example_RouteComposer_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RouteComposer_Example_RouteComposer_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CAEB75B5743692F14542043ACD7659C4 /* CompleteFactoryAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = CompleteFactoryAssembly.html; path = docs/Classes/CompleteFactoryAssembly.html; sourceTree = ""; }; + CAF2B9DAE7973DA0642808432B1658EC /* NavigationControllerActions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = NavigationControllerActions.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/NavigationControllerActions.html; sourceTree = ""; }; + CB1C0397236C7C50682C1B5E8C6249FC /* SetAsMasterAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SetAsMasterAction.html; path = docs/Structs/SplitViewControllerActions/SetAsMasterAction.html; sourceTree = ""; }; CDEE4C779C937976FE4511F288EAEC26 /* RoutingInterceptorBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RoutingInterceptorBox.swift; sourceTree = ""; }; CE5F3C77DE076529171BC5A160964707 /* NavigationControllerFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NavigationControllerFactory.swift; sourceTree = ""; }; - CEF9B4108166C114FCA45D6EB8F61ACD /* Resulting Enums.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Resulting Enums.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Resulting Enums.html"; sourceTree = ""; }; - CF1F458C909182BE73EE6F94564FE382 /* WindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; name = WindowProvider.html; path = docs/Protocols/WindowProvider.html; sourceTree = ""; }; - D007D22116DCB6B935077E855444A98A /* CompleteFactoryChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = CompleteFactoryChainAssembly.html; path = docs/Classes/CompleteFactoryChainAssembly.html; sourceTree = ""; }; - D151520EF765D9758825C14EC608EAD9 /* PostRoutingTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PostRoutingTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/PostRoutingTask.html; sourceTree = ""; }; - D1ED1FF55AA36739E07F0ACE03FBFD48 /* InstanceFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InstanceFinder.html; path = docs/Structs/InstanceFinder.html; sourceTree = ""; }; - D2B86448B906F49E880BD753D3AFB185 /* readme.html */ = {isa = PBXFileReference; includeInIndex = 1; name = readme.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/readme.html; sourceTree = ""; }; + CEF9B4108166C114FCA45D6EB8F61ACD /* Resulting Enums.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Resulting Enums.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Resulting Enums.html"; sourceTree = ""; }; + CF1F458C909182BE73EE6F94564FE382 /* WindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = WindowProvider.html; path = docs/Protocols/WindowProvider.html; sourceTree = ""; }; + D007D22116DCB6B935077E855444A98A /* CompleteFactoryChainAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = CompleteFactoryChainAssembly.html; path = docs/Classes/CompleteFactoryChainAssembly.html; sourceTree = ""; }; + D151520EF765D9758825C14EC608EAD9 /* PostRoutingTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = PostRoutingTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/PostRoutingTask.html; sourceTree = ""; }; + D1ED1FF55AA36739E07F0ACE03FBFD48 /* InstanceFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = InstanceFinder.html; path = docs/Structs/InstanceFinder.html; sourceTree = ""; }; + D2B86448B906F49E880BD753D3AFB185 /* readme.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = readme.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/readme.html; sourceTree = ""; }; D2D23A33521AE9668A7171D2752CEF61 /* PreparableEntity.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PreparableEntity.swift; sourceTree = ""; }; - D33E78D61D3D266003A5A2BC66BEEA25 /* PresentModallyAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PresentModallyAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ViewControllerActions/PresentModallyAction.html; sourceTree = ""; }; - D34A93BD5E95A260A116F7E3AB100E7E /* CompleteFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = CompleteFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/CompleteFactory.html; sourceTree = ""; }; + D33E78D61D3D266003A5A2BC66BEEA25 /* PresentModallyAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = PresentModallyAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/ViewControllerActions/PresentModallyAction.html; sourceTree = ""; }; + D34A93BD5E95A260A116F7E3AB100E7E /* CompleteFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = CompleteFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/CompleteFactory.html; sourceTree = ""; }; D3CCCCDCECC74B48CEB175722E337ED1 /* InterceptorMultiplexer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = InterceptorMultiplexer.swift; sourceTree = ""; }; - D484D1F4003B75A538ED3F78140AA8A3 /* DefaultLogger.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DefaultLogger.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultLogger.html; sourceTree = ""; }; - D5A943AE239320FEE17CA84A50CE22FE /* CompleteFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = CompleteFactory.html; path = docs/Structs/CompleteFactory.html; sourceTree = ""; }; - D5DD2E17C8CAF906527C541F7414AAF6 /* ContextChecking.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContextChecking.html; path = docs/Protocols/ContextChecking.html; sourceTree = ""; }; - D711C9ABAB83F7C2E74EFF540EA0076A /* SwitchAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SwitchAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SwitchAssembly.html; sourceTree = ""; }; + D484D1F4003B75A538ED3F78140AA8A3 /* DefaultLogger.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = DefaultLogger.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DefaultLogger.html; sourceTree = ""; }; + D5A943AE239320FEE17CA84A50CE22FE /* CompleteFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = CompleteFactory.html; path = docs/Structs/CompleteFactory.html; sourceTree = ""; }; + D5DD2E17C8CAF906527C541F7414AAF6 /* ContextChecking.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContextChecking.html; path = docs/Protocols/ContextChecking.html; sourceTree = ""; }; + D711C9ABAB83F7C2E74EFF540EA0076A /* SwitchAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SwitchAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SwitchAssembly.html; sourceTree = ""; }; D81B8F35D82987B82212331A1D193C93 /* CompleteFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CompleteFactory.swift; sourceTree = ""; }; D871AA46E131C1B7981E9540D723F34F /* TabBarControllerStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TabBarControllerStep.swift; sourceTree = ""; }; - D98C2FA9A8B225EC574B9A548F25CC2A /* StoryboardFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StoryboardFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/StoryboardFactory.html; sourceTree = ""; }; - D9C77889210024F187C66B52A62AA389 /* RoutingError.html */ = {isa = PBXFileReference; includeInIndex = 1; name = RoutingError.html; path = docs/Enums/RoutingError.html; sourceTree = ""; }; - D9E6886D94E5E763D89F48925E79B74D /* SimpleContainerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SimpleContainerFactory.html; path = docs/Protocols/SimpleContainerFactory.html; sourceTree = ""; }; - DAD36C5F8FBA4A23BC755E1FC26087B8 /* CustomWindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; name = CustomWindowProvider.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/CustomWindowProvider.html; sourceTree = ""; }; - DB219F23931894FA442E3C7B833E3567 /* WindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; name = WindowProvider.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/WindowProvider.html; sourceTree = ""; }; - DB44B674A5C69D731E4B32260B858134 /* ContainerAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerAction.html; path = docs/Protocols/ContainerAction.html; sourceTree = ""; }; - DB754295650A96C6D2C7432E89D62F33 /* ActionConnecting.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ActionConnecting.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ActionConnecting.html; sourceTree = ""; }; - DBCEB7EBC9104192DC696AC494193211 /* Logging.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Logging.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Logging.html; sourceTree = ""; }; + D98C2FA9A8B225EC574B9A548F25CC2A /* StoryboardFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = StoryboardFactory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/StoryboardFactory.html; sourceTree = ""; }; + D9C77889210024F187C66B52A62AA389 /* RoutingError.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = RoutingError.html; path = docs/Enums/RoutingError.html; sourceTree = ""; }; + D9E6886D94E5E763D89F48925E79B74D /* SimpleContainerFactory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SimpleContainerFactory.html; path = docs/Protocols/SimpleContainerFactory.html; sourceTree = ""; }; + DAD36C5F8FBA4A23BC755E1FC26087B8 /* CustomWindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = CustomWindowProvider.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/CustomWindowProvider.html; sourceTree = ""; }; + DB219F23931894FA442E3C7B833E3567 /* WindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = WindowProvider.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/WindowProvider.html; sourceTree = ""; }; + DB44B674A5C69D731E4B32260B858134 /* ContainerAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ContainerAction.html; path = docs/Protocols/ContainerAction.html; sourceTree = ""; }; + DB754295650A96C6D2C7432E89D62F33 /* ActionConnecting.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ActionConnecting.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/ActionConnecting.html; sourceTree = ""; }; + DBCEB7EBC9104192DC696AC494193211 /* Logging.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Logging.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Logging.html; sourceTree = ""; }; DC06F87E7752BDEB7D9ADBB28FE4627F /* PostRoutingTaskMultiplexer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PostRoutingTaskMultiplexer.swift; sourceTree = ""; }; - DD0FDF14B751A8BB766EB66C15CD0097 /* UITabBarController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UITabBarController.html; path = docs/Extensions/UITabBarController.html; sourceTree = ""; }; - DD95E66646365601DE15DA1F19FF1E5F /* DismissalMethodProvidingContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DismissalMethodProvidingContextTask.html; path = docs/Structs/DismissalMethodProvidingContextTask.html; sourceTree = ""; }; - DEB4613C9802643BEE59BA2266356C08 /* SingleContainerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SingleContainerStep.html; path = docs/Classes/SingleContainerStep.html; sourceTree = ""; }; + DD0FDF14B751A8BB766EB66C15CD0097 /* UITabBarController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = UITabBarController.html; path = docs/Extensions/UITabBarController.html; sourceTree = ""; }; + DD95E66646365601DE15DA1F19FF1E5F /* DismissalMethodProvidingContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = DismissalMethodProvidingContextTask.html; path = docs/Structs/DismissalMethodProvidingContextTask.html; sourceTree = ""; }; + DEB4613C9802643BEE59BA2266356C08 /* SingleContainerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = SingleContainerStep.html; path = docs/Classes/SingleContainerStep.html; sourceTree = ""; }; DEFAFF57B005E14E85CCBA10E679B7D4 /* RouteComposer-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "RouteComposer-prefix.pch"; sourceTree = ""; }; DF1A5EE335C43D9CE7C4040666D8732D /* NavigationController+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "NavigationController+Extension.swift"; sourceTree = ""; }; - DF415CFB4FFABFD15C12CEE2A96DD586 /* GenericStepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; name = GenericStepAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/GenericStepAssembly.html; sourceTree = ""; }; - E0E82B6EBEAD31057033B33183635409 /* KeyWindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; name = KeyWindowProvider.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/KeyWindowProvider.html; sourceTree = ""; }; + DF415CFB4FFABFD15C12CEE2A96DD586 /* GenericStepAssembly.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = GenericStepAssembly.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/GenericStepAssembly.html; sourceTree = ""; }; + E0E82B6EBEAD31057033B33183635409 /* KeyWindowProvider.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = KeyWindowProvider.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/KeyWindowProvider.html; sourceTree = ""; }; E2092952257F2E4009FB811B09458320 /* RouteComposer-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "RouteComposer-dummy.m"; sourceTree = ""; }; - E241A5B430FE9CEF02ACCC1FEF7DC87F /* UISplitViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UISplitViewController.html; path = docs/Extensions/UISplitViewController.html; sourceTree = ""; }; + E241A5B430FE9CEF02ACCC1FEF7DC87F /* UISplitViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = UISplitViewController.html; path = docs/Extensions/UISplitViewController.html; sourceTree = ""; }; E25201B747082FBC69C7D0B5ADF07855 /* DefaultStackIterator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DefaultStackIterator.swift; sourceTree = ""; }; - E3C704FA8A835C2BE07557CED8F57046 /* readme.html */ = {isa = PBXFileReference; includeInIndex = 1; name = readme.html; path = docs/readme.html; sourceTree = ""; }; - E438403A51FEE05D90470D4104B1C47C /* DismissalMethodProvidingContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DismissalMethodProvidingContextTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DismissalMethodProvidingContextTask.html; sourceTree = ""; }; + E3C704FA8A835C2BE07557CED8F57046 /* readme.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = readme.html; path = docs/readme.html; sourceTree = ""; }; + E438403A51FEE05D90470D4104B1C47C /* DismissalMethodProvidingContextTask.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = DismissalMethodProvidingContextTask.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/DismissalMethodProvidingContextTask.html; sourceTree = ""; }; E5CDCD6AE95060B5F96D5A0E2F15ABDF /* Pods-RouteComposer_Example-RouteComposer_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-RouteComposer_Example-RouteComposer_Tests.release.xcconfig"; sourceTree = ""; }; E60003D95B7E1AD0ECD996B077ACF276 /* ClassFinder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ClassFinder.swift; sourceTree = ""; }; - E70C0008FC63BC38D38F76C11FB56C9D /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; - E769C063A4176DF5BD644AC0CC43B801 /* PresentModallyAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = PresentModallyAction.html; path = docs/Structs/ViewControllerActions/PresentModallyAction.html; sourceTree = ""; }; - E773C72D088E373166F7CBA952B9620A /* jquery.min.js */ = {isa = PBXFileReference; includeInIndex = 1; name = jquery.min.js; path = docs/js/jquery.min.js; sourceTree = ""; }; + E70C0008FC63BC38D38F76C11FB56C9D /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + E769C063A4176DF5BD644AC0CC43B801 /* PresentModallyAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = PresentModallyAction.html; path = docs/Structs/ViewControllerActions/PresentModallyAction.html; sourceTree = ""; }; + E773C72D088E373166F7CBA952B9620A /* jquery.min.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jquery.min.js; path = docs/js/jquery.min.js; sourceTree = ""; }; E80395DDFEDBCBDFB4AD934100ADEC67 /* Router.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Router.swift; path = RouteComposer/Classes/Router.swift; sourceTree = ""; }; - E978709098C662E8B682083192372029 /* DefaultRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DefaultRouter.html; path = docs/Structs/DefaultRouter.html; sourceTree = ""; }; - E9EF5B27DD375BBA748C5C48215D3448 /* LogLevel.html */ = {isa = PBXFileReference; includeInIndex = 1; name = LogLevel.html; path = docs/Structs/DefaultLogger/LogLevel.html; sourceTree = ""; }; - EAA5C35B5BFC206DCCE28CC7824E35FD /* StackIteratingFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; name = StackIteratingFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/StackIteratingFinder.html; sourceTree = ""; }; - EB07DFDF4B12CD4F7845C7E4FA250E01 /* Other Guides.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Guides.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Guides.html"; sourceTree = ""; }; + E978709098C662E8B682083192372029 /* DefaultRouter.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = DefaultRouter.html; path = docs/Structs/DefaultRouter.html; sourceTree = ""; }; + E9EF5B27DD375BBA748C5C48215D3448 /* LogLevel.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = LogLevel.html; path = docs/Structs/DefaultLogger/LogLevel.html; sourceTree = ""; }; + EAA5C35B5BFC206DCCE28CC7824E35FD /* StackIteratingFinder.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = StackIteratingFinder.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/StackIteratingFinder.html; sourceTree = ""; }; + EB07DFDF4B12CD4F7845C7E4FA250E01 /* Other Guides.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Other Guides.html"; path = "docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Other Guides.html"; sourceTree = ""; }; EBC1BE6AB173E0C52BE67AEA50853718 /* ContainerStepAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContainerStepAssembly.swift; sourceTree = ""; }; - EBC498A89DE5B184699CF17A35DBD5C1 /* InlineInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; name = InlineInterceptor.html; path = docs/Structs/InlineInterceptor.html; sourceTree = ""; }; + EBC498A89DE5B184699CF17A35DBD5C1 /* InlineInterceptor.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = InlineInterceptor.html; path = docs/Structs/InlineInterceptor.html; sourceTree = ""; }; ECF2A2B0720AE923C22BED3192888BE0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - ED347A5021995666A1316A1EEA78C4B9 /* UINavigationController.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UINavigationController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UINavigationController.html; sourceTree = ""; }; - EDB39F545D57687020666252ECB36DA3 /* Pods_RouteComposer_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_RouteComposer_Example.framework; path = "Pods-RouteComposer_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - EEF7050C2DB586748384A479961A245D /* UIViewController's protocols.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "UIViewController's protocols.html"; path = "docs/UIViewController's protocols.html"; sourceTree = ""; }; - EF6D1530EA8D1A2AAFEA6380467B3C34 /* RoutingResult.html */ = {isa = PBXFileReference; includeInIndex = 1; name = RoutingResult.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/RoutingResult.html; sourceTree = ""; }; - EFB28F20FC98313F33C8427F0F5CFCF3 /* SplitControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = SplitControllerStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SplitControllerStep.html; sourceTree = ""; }; - F0A64E641B7690BEC20C4DDBA9592254 /* AddTabAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = AddTabAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/TabBarControllerActions/AddTabAction.html; sourceTree = ""; }; + ED347A5021995666A1316A1EEA78C4B9 /* UINavigationController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = UINavigationController.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UINavigationController.html; sourceTree = ""; }; + EDB39F545D57687020666252ECB36DA3 /* Pods_RouteComposer_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RouteComposer_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EEF7050C2DB586748384A479961A245D /* UIViewController's protocols.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "UIViewController's protocols.html"; path = "docs/UIViewController's protocols.html"; sourceTree = ""; }; + EF6D1530EA8D1A2AAFEA6380467B3C34 /* RoutingResult.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = RoutingResult.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Enums/RoutingResult.html; sourceTree = ""; }; + EFB28F20FC98313F33C8427F0F5CFCF3 /* SplitControllerStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = SplitControllerStep.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Classes/SplitControllerStep.html; sourceTree = ""; }; + F0A64E641B7690BEC20C4DDBA9592254 /* AddTabAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = AddTabAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Structs/TabBarControllerActions/AddTabAction.html; sourceTree = ""; }; F166B53BD5C2209EE9145C43787C4B16 /* InterceptableRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = InterceptableRouter.swift; path = RouteComposer/Classes/InterceptableRouter.swift; sourceTree = ""; }; - F3B7FB5CC6535D100B9574F64D9B7EF7 /* DestinationStep.html */ = {isa = PBXFileReference; includeInIndex = 1; name = DestinationStep.html; path = docs/Structs/DestinationStep.html; sourceTree = ""; }; - F47A582CF03EDBD3BCC34A6C177C1C67 /* search.json */ = {isa = PBXFileReference; includeInIndex = 1; name = search.json; path = docs/search.json; sourceTree = ""; }; + F3B7FB5CC6535D100B9574F64D9B7EF7 /* DestinationStep.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = DestinationStep.html; path = docs/Structs/DestinationStep.html; sourceTree = ""; }; + F47A582CF03EDBD3BCC34A6C177C1C67 /* search.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = search.json; path = docs/search.json; sourceTree = ""; }; F4934B3129210C81801D568D842E5B74 /* InlineTasks.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = InlineTasks.swift; path = RouteComposer/Classes/InlineTasks.swift; sourceTree = ""; }; - F517E30CE5DAB8E4EDE7BF6808B90503 /* Logging.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Logging.html; path = docs/Logging.html; sourceTree = ""; }; + F517E30CE5DAB8E4EDE7BF6808B90503 /* Logging.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Logging.html; path = docs/Logging.html; sourceTree = ""; }; F557D1B98E7C1D1ABEDB06C9237872D1 /* Pods-RouteComposer_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-RouteComposer_Example-Info.plist"; sourceTree = ""; }; - F5C52BDE483CBB30D704590184A0AB6B /* Steps.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Steps.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Steps.html; sourceTree = ""; }; - F5C685F4B0F24C0AE0C422C4818D1DBA /* Other Guides.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Guides.html"; path = "docs/Other Guides.html"; sourceTree = ""; }; + F5C52BDE483CBB30D704590184A0AB6B /* Steps.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Steps.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Steps.html; sourceTree = ""; }; + F5C685F4B0F24C0AE0C422C4818D1DBA /* Other Guides.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Other Guides.html"; path = "docs/Other Guides.html"; sourceTree = ""; }; F6F29F99F1EC68A022E6F9DB0AC583A7 /* AbstractAction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AbstractAction.swift; path = RouteComposer/Classes/AbstractAction.swift; sourceTree = ""; }; - F6FD2A70FA6DEEB6536E69606AF743C7 /* AbstractAction.html */ = {isa = PBXFileReference; includeInIndex = 1; name = AbstractAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/AbstractAction.html; sourceTree = ""; }; + F6FD2A70FA6DEEB6536E69606AF743C7 /* AbstractAction.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = AbstractAction.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/AbstractAction.html; sourceTree = ""; }; F70F03FFAC8AD6BA993892DE2FFDDFF6 /* StepChainAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StepChainAssembly.swift; sourceTree = ""; }; - F748CADF7FC9B83A6FCAB735EF7CED73 /* ChildCoordinator.html */ = {isa = PBXFileReference; includeInIndex = 1; name = ChildCoordinator.html; path = docs/Structs/ChildCoordinator.html; sourceTree = ""; }; + F748CADF7FC9B83A6FCAB735EF7CED73 /* ChildCoordinator.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ChildCoordinator.html; path = docs/Structs/ChildCoordinator.html; sourceTree = ""; }; F800B0999951B9C2768B71B30391F134 /* RouteComposer-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "RouteComposer-Info.plist"; sourceTree = ""; }; - F9284855700821EF799C4BF16BD77841 /* Other Protocols.html */ = {isa = PBXFileReference; includeInIndex = 1; name = "Other Protocols.html"; path = "docs/Other Protocols.html"; sourceTree = ""; }; + F9284855700821EF799C4BF16BD77841 /* Other Protocols.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Other Protocols.html"; path = "docs/Other Protocols.html"; sourceTree = ""; }; F9AFA09BD180494B1EAC2F077492BA8A /* SingleStep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SingleStep.swift; sourceTree = ""; }; - FA013020F5D4D9C27DFFCD2F7060D767 /* Factory.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Factory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Factory.html; sourceTree = ""; }; - FB205CFFBF34BABB61F98AFDC8C7DFCE /* Factories.html */ = {isa = PBXFileReference; includeInIndex = 1; name = Factories.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Factories.html; sourceTree = ""; }; + FA013020F5D4D9C27DFFCD2F7060D767 /* Factory.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Factory.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Protocols/Factory.html; sourceTree = ""; }; + FB205CFFBF34BABB61F98AFDC8C7DFCE /* Factories.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Factories.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Factories.html; sourceTree = ""; }; FC8437F9580D49E48C8A52744FC1F716 /* DefaultLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DefaultLogger.swift; sourceTree = ""; }; - FEC9FD994EACAB5CB88CA2C4BABD016C /* UIWindow.html */ = {isa = PBXFileReference; includeInIndex = 1; name = UIWindow.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UIWindow.html; sourceTree = ""; }; + FEC9FD994EACAB5CB88CA2C4BABD016C /* UIWindow.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = UIWindow.html; path = docs/docsets/RouteComposer.docset/Contents/Resources/Documents/Extensions/UIWindow.html; sourceTree = ""; }; FF58D0F490DA9189DBEEEA9DD4EFB0F8 /* Pods-RouteComposer_Example-RouteComposer_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-RouteComposer_Example-RouteComposer_Tests.modulemap"; sourceTree = ""; }; FF9D5021B74885BBD5CC23875B65F8CA /* LogMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LogMessage.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -603,7 +603,6 @@ 1974DFD21D7D0B0FBF528625873C9393 /* StackIterator.swift */, 28C5DABC229D49A709B9F77EC7912974 /* WindowProvider.swift */, ); - name = "Stack Iterator"; path = "Stack Iterator"; sourceTree = ""; }; @@ -640,7 +639,6 @@ 86CB6CA80AE3011435A5E0918CFF8793 /* AnyRoutingInterceptor.swift */, 3A93C6E2D571EADB4517AA42BABD3ED3 /* Boxes */, ); - name = "Type Erasure"; path = "Type Erasure"; sourceTree = ""; }; @@ -658,7 +656,6 @@ B998708092DC44730F16CA81AB757E47 /* PostRoutingTaskBox.swift */, CDEE4C779C937976FE4511F288EAEC26 /* RoutingInterceptorBox.swift */, ); - name = Boxes; path = Boxes; sourceTree = ""; }; @@ -1064,7 +1061,6 @@ D3CCCCDCECC74B48CEB175722E337ED1 /* InterceptorMultiplexer.swift */, DC06F87E7752BDEB7D9ADBB28FE4627F /* PostRoutingTaskMultiplexer.swift */, ); - name = Multiplexers; path = Multiplexers; sourceTree = ""; }; @@ -1110,7 +1106,6 @@ 89B4422091B4BEDD1C715D17F17CB9C4 /* RoutingStep.swift */, 533516216035BF0B7F9F2371327AB11D /* SwitcherStep.swift */, ); - name = Internal; path = Internal; sourceTree = ""; }; @@ -1184,7 +1179,6 @@ F70F03FFAC8AD6BA993892DE2FFDDFF6 /* StepChainAssembly.swift */, 1AB8EE43049793FB4D4E69AEDDF957E1 /* TaskCollector.swift */, ); - name = Helpers; path = Helpers; sourceTree = ""; }; @@ -1321,13 +1315,14 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0930; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1020; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; @@ -1663,10 +1658,12 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_CODE_COVERAGE = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; @@ -1791,10 +1788,12 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_CODE_COVERAGE = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; @@ -1840,8 +1839,7 @@ MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.2; SYMROOT = "${SRCROOT}/../build"; }; diff --git a/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/RouteComposer.xcscheme b/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/RouteComposer.xcscheme index 364f0bca4..1ecc9e53e 100644 --- a/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/RouteComposer.xcscheme +++ b/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/RouteComposer.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + codeCoverageEnabled = "YES" shouldUseLaunchSchemeArgsEnv = "YES"> diff --git a/README.md b/README.md index 7a04eb958..0dfd9d523 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Swift 5.0](https://img.shields.io/badge/language-Swift5.0-orange.svg?style=flat)](https://developer.apple.com/swift) [![Platform iOS](https://img.shields.io/badge/platform-iOS-yellow.svg)](https://www.apple.com/ios) [![Documentation](https://saksdirect.github.io/route-composer/badge.svg)](https://saksdirect.github.io/route-composer) -![Code coverage](https://img.shields.io/badge/code%20coverage-86%25-green.svg?style=flat) +[![Code coverage](https://img.shields.io/badge/code%20coverage-83%25-green.svg?style=flat)](https://saksdirect.github.io/route-composer/tests/index.html) [![MIT License](https://img.shields.io/cocoapods/l/RouteComposer.svg?style=flat)](https://github.com/saksdirect/RouteComposer/blob/master/LICENSE) [![Twitter](https://img.shields.io/twitter/url/https/github.com/saksdirect/route-composer.svg?style=flat)](https://twitter.com/intent/tweet?text=Check%20it%20out:&url=https%3A%2F%2Fgithub.com%2Fsaksdirect%2Froute-composer) diff --git a/docs/tests/AbstractFactory.swift.html b/docs/tests/AbstractFactory.swift.html new file mode 100644 index 000000000..0ec828fb1 --- /dev/null +++ b/docs/tests/AbstractFactory.swift.html @@ -0,0 +1,262 @@ + + + +AbstractFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "AbstractFactory.swift" : 50.00% +

+

(3 of 6 relevant lines covered)

+

RouteComposer/Classes/AbstractFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 30/07/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Base protocol for all types of factories.
9
/// An instance that extends `AbstractFactory` builds a `UIViewController` that will later be
10
/// integrated into the stack by the `Router`
11
public protocol AbstractFactory {
12
13
    /// Type of `UIViewController` that `AbstractFactory` can build
14
    associatedtype ViewController: UIViewController
15
16
    /// `Context` to be passed into `UIViewController`
17
    associatedtype Context
18
19
    /// The `Router` will call it before the navigation process and if the `AbstractFactory` is not able to
20
    /// build a view controller it should throw an exception. (example: it has to build a product view
21
    //  controller but there is no product code in context)
22
    ///
23
    /// - Parameter context: A `Context` instance that is provided to the `Router`.
24
    /// - Throws: The `RoutingError` if the `Factory` cannot prepare to build a `UIViewController` instance
25
    ///   with the `Context` instance provided.
26
    mutating func prepare(with context: Context) throws
27
28
}
29
30
/// Default implementation for any context
31
public extension AbstractFactory where Context == Any? {
32
33
    /// Prepares the `AbstractFactory`
34
    mutating func prepare() throws {
5x
35
        try prepare(with: nil)
5x
36
    }
5x
37
38
}
39
40
/// Default implementation for any context
41
public extension AbstractFactory where Context == Void {
42
43
    /// Prepares the `AbstractFactory`
44
    mutating func prepare() throws {
!
45
        try prepare(with: ())
!
46
    }
!
47
48
}
+
+ + + diff --git a/docs/tests/Action.swift.html b/docs/tests/Action.swift.html new file mode 100644 index 000000000..d89ddec2b --- /dev/null +++ b/docs/tests/Action.swift.html @@ -0,0 +1,182 @@ + + + +Action.swift - Slather + + + +
Slather logo
+

+Coverage for "Action.swift" : 100.00% +

+

(3 of 3 relevant lines covered)

+

RouteComposer/Classes/Action.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// Represents an action that has to be applied to the `UIViewController` after it has
9
/// been built (eg: push to navigation stack, present modally, push to tab, etc)
10
public protocol Action: AbstractAction {
11
}
12
13
/// Represents an action to be used by a `ContainerFactory` to build it's children view controller stack
14
public protocol ContainerAction: AbstractAction where ViewController: ContainerViewController {
15
16
    /// If current `UIViewController` has to be pushed/added/etc to the existing stack of the view controllers,
17
    /// this method should be called instead.
18
    ///
19
    /// - Parameters:
20
    ///   - viewController: The `UIViewController` to be embedded.
21
    ///   - childViewControllers: The stack of the `UIViewController`s in the current container.
22
    func perform(embedding viewController: UIViewController, in childViewControllers: inout [UIViewController]) throws
23
24
}
25
26
public extension ContainerAction {
27
28
    func perform(embedding viewController: UIViewController, in childViewControllers: inout [UIViewController]) {
33x
29
        childViewControllers.append(viewController)
33x
30
    }
33x
31
32
}
+
+ + + diff --git a/docs/tests/ActionBox.swift.html b/docs/tests/ActionBox.swift.html new file mode 100644 index 000000000..c20ed81a5 --- /dev/null +++ b/docs/tests/ActionBox.swift.html @@ -0,0 +1,257 @@ + + + +ActionBox.swift - Slather + + + +
Slather logo
+

+Coverage for "ActionBox.swift" : 76.92% +

+

(20 of 26 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/ActionBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
struct ActionBox<A: Action>: AnyAction, AnyActionBox, CustomStringConvertible, MainThreadChecking {
8
9
    let action: A
10
11
    init(_ action: A) {
212x
12
        self.action = action
212x
13
    }
212x
14
15
    func perform(with viewController: UIViewController,
16
                 on existingController: UIViewController,
17
                 with delayedIntegrationHandler: DelayedActionIntegrationHandler,
18
                 nextAction: AnyAction?,
19
                 animated: Bool,
20
                 completion: @escaping (ActionResult) -> Void) {
57x
21
        guard let typedExistingViewController = existingController as? A.ViewController else {
57x
22
            completion(.failure(RoutingError.typeMismatch(ActionType.ViewController.self, .init("Action \(action.self) cannot " +
!
23
                    "be performed on \(existingController)."))))
!
24
            return
!
25
        }
57x
26
        assertIfNotMainThread()
57x
27
        delayedIntegrationHandler.purge(animated: animated, completion: {
57x
28
            self.action.perform(with: viewController, on: typedExistingViewController, animated: animated) { result in
57x
29
                self.assertIfNotMainThread()
56x
30
                completion(result)
56x
31
            }
56x
32
        })
57x
33
    }
57x
34
35
    func perform(embedding viewController: UIViewController, in childViewControllers: inout [UIViewController]) {
!
36
        childViewControllers.append(viewController)
!
37
    }
!
38
39
    public var description: String {
52x
40
        return String(describing: action)
52x
41
    }
52x
42
43
    func isEmbeddable(to container: ContainerViewController.Type) -> Bool {
9x
44
        return false
9x
45
    }
9x
46
47
}
+
+ + + diff --git a/docs/tests/ActionConnectingAssembly.swift.html b/docs/tests/ActionConnectingAssembly.swift.html new file mode 100644 index 000000000..91dda5c38 --- /dev/null +++ b/docs/tests/ActionConnectingAssembly.swift.html @@ -0,0 +1,202 @@ + + + +ActionConnectingAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "ActionConnectingAssembly.swift" : 100.00% +

+

(18 of 18 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/ActionConnectingAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 31/08/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Helper class to build a chain of steps. Can not be used directly.
9
public struct ActionConnectingAssembly<PVC: UIViewController, VC: UIViewController, C>: ActionConnecting {
10
11
    let previousSteps: [RoutingStep]
12
13
    let stepToFullFill: ActionToStepIntegrator<PVC, C>
14
15
    init(stepToFullFill: ActionToStepIntegrator<PVC, C>, previousSteps: [RoutingStep] = []) {
41x
16
        self.previousSteps = previousSteps
41x
17
        self.stepToFullFill = stepToFullFill
41x
18
    }
41x
19
20
    public func using<A: Action>(_ action: A) -> StepChainAssembly<VC, C> {
34x
21
        var previousSteps = self.previousSteps
34x
22
        if let routingStep = stepToFullFill.routingStep(with: action) {
34x
23
            previousSteps.append(routingStep)
34x
24
        }
34x
25
        return StepChainAssembly(previousSteps: previousSteps)
34x
26
    }
34x
27
28
    public func using<A: ContainerAction>(_ action: A) -> ContainerStepChainAssembly<A.ViewController, VC, C> {
7x
29
        var previousSteps = self.previousSteps
7x
30
        if let routingStep = stepToFullFill.embeddableRoutingStep(with: action) {
7x
31
            previousSteps.append(routingStep)
7x
32
        }
7x
33
        return ContainerStepChainAssembly(previousSteps: previousSteps)
7x
34
    }
7x
35
36
}
+
+ + + diff --git a/docs/tests/ActionResult.swift.html b/docs/tests/ActionResult.swift.html new file mode 100644 index 000000000..eba1d192b --- /dev/null +++ b/docs/tests/ActionResult.swift.html @@ -0,0 +1,197 @@ + + + +ActionResult.swift - Slather + + + +
Slather logo
+

+Coverage for "ActionResult.swift" : 0.00% +

+

(0 of 6 relevant lines covered)

+

RouteComposer/Classes/ActionResult.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  ActionResult.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 08/02/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
/// The result of the `Action`'s `AbstractAction.perform(...)` method.
12
///
13
/// - continueRouting: The `Action` was able to integrate a view controller into the stack
14
/// - failure: The `Action` was not able to integrate a view controller into the stack. Navigation process should not continue
15
public enum ActionResult {
16
17
    /** The `Action` was able to build a view controller into the stack. */
18
    case continueRouting
19
20
    /** The `Action` was not able to build a view controller into the stack. Navigation should not continue */
21
    case failure(Error)
22
23
}
24
25
public extension ActionResult {
26
27
    /// Returns `true` if `ActionResult` is `.continueRouting`
28
    var isSuccessful: Bool {
!
29
        guard case .continueRouting = self else {
!
30
            return false
!
31
        }
!
32
        return true
!
33
    }
!
34
35
}
+
+ + + diff --git a/docs/tests/ActionToStepIntegrator.swift.html b/docs/tests/ActionToStepIntegrator.swift.html new file mode 100644 index 000000000..96db1caa4 --- /dev/null +++ b/docs/tests/ActionToStepIntegrator.swift.html @@ -0,0 +1,322 @@ + + + +ActionToStepIntegrator.swift - Slather + + + +
Slather logo
+

+Coverage for "ActionToStepIntegrator.swift" : 100.00% +

+

(21 of 21 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/ActionToStepIntegrator.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 23/01/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// A simple class that represents an intermediate `DestinationStep` and allows to add tasks to it.
9
public class ActionToStepIntegrator<VC: UIViewController, C>: InterceptableStepAssembling {
10
11
    public typealias ViewController = VC
12
13
    public typealias Context = C
14
15
    var taskCollector: TaskCollector
16
17
    init(taskCollector: TaskCollector = TaskCollector()) {
55x
18
        self.taskCollector = taskCollector
55x
19
    }
55x
20
    /// Adds `RoutingInterceptor` instance.
21
    /// This action does not contain type safety checks to avoid complications.
22
    ///
23
    /// - Parameter interceptor: The `RoutingInterceptor` instance to be executed by `Router` before the navigation process
24
    ///   to this step.
25
    public final func adding<RI: RoutingInterceptor>(_ interceptor: RI) -> Self where RI.Context == Context {
1x
26
        taskCollector.add(interceptor)
1x
27
        return self
1x
28
    }
1x
29
30
    /// Adds `ContextTask` instance
31
    ///
32
    /// - Parameter contextTask: The `ContextTask` instance to be applied by a `Router` immediately after it
33
    ///   will find or create `UIViewController`.
34
    public final func adding<CT: ContextTask>(_ contextTask: CT) -> Self
35
            where
36
            CT.ViewController == ViewController, CT.Context == Context {
1x
37
        taskCollector.add(contextTask)
1x
38
        return self
1x
39
    }
1x
40
41
    /// Adds `PostRoutingTask` instance.
42
    /// This action does not contain type safety checks to avoid complications.
43
    ///
44
    /// - Parameter postTask: The `PostRoutingTask` instance to be executed by a `Router` after the navigation process.
45
    public final func adding<PT: PostRoutingTask>(_ postTask: PT) -> Self where PT.Context == Context {
1x
46
        taskCollector.add(postTask)
1x
47
        return self
1x
48
    }
1x
49
50
    // Hides action integration from library user.
51
    func routingStep<A: Action>(with action: A) -> RoutingStep? {
1x
52
        return nil
1x
53
    }
1x
54
55
    // Hides action integration from library user.
56
    func embeddableRoutingStep<A: ContainerAction>(with action: A) -> RoutingStep? {
1x
57
        return nil
1x
58
    }
1x
59
60
}
+
+ + + diff --git a/docs/tests/AnyFactoryBox.swift.html b/docs/tests/AnyFactoryBox.swift.html new file mode 100644 index 000000000..b7de167fd --- /dev/null +++ b/docs/tests/AnyFactoryBox.swift.html @@ -0,0 +1,277 @@ + + + +AnyFactoryBox.swift - Slather + + + +
Slather logo
+

+Coverage for "AnyFactoryBox.swift" : 86.67% +

+

(13 of 15 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/AnyFactoryBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
protocol AnyFactoryBox: AnyFactory {
8
9
    associatedtype FactoryType: AbstractFactory
10
11
    var factory: FactoryType { get set }
12
13
    init?(_ factory: FactoryType, action: AnyAction)
14
15
}
16
17
protocol PreparableAnyFactory: AnyFactory, PreparableEntity {
18
19
    var isPrepared: Bool { get set }
20
21
}
22
23
extension AnyFactoryBox where Self: AnyFactory {
24
25
    mutating func scrapeChildren(from factories: [AnyFactory]) throws -> [AnyFactory] {
87x
26
        return factories
87x
27
    }
87x
28
29
}
30
31
extension AnyFactoryBox where Self: PreparableAnyFactory, Self: MainThreadChecking {
32
33
    mutating func prepare(with context: Any?) throws {
133x
34
        assertIfNotMainThread()
133x
35
        guard let typedContext = Any?.some(context as Any) as? FactoryType.Context else {
133x
36
            throw RoutingError.typeMismatch(FactoryType.Context.self, .init("\(String(describing: factory.self)) does " +
!
37
                    "not accept \(String(describing: context.self)) as a context."))
!
38
        }
133x
39
        try factory.prepare(with: typedContext)
133x
40
        isPrepared = true
133x
41
    }
133x
42
43
}
44
45
extension AnyFactory where Self: CustomStringConvertible & AnyFactoryBox {
46
47
    var description: String {
318x
48
        return String(describing: factory)
318x
49
    }
318x
50
51
}
+
+ + + diff --git a/docs/tests/Array+Extension.swift.html b/docs/tests/Array+Extension.swift.html new file mode 100644 index 000000000..4a7c884c4 --- /dev/null +++ b/docs/tests/Array+Extension.swift.html @@ -0,0 +1,247 @@ + + + +Array+Extension.swift - Slather + + + +
Slather logo
+

+Coverage for "Array+Extension.swift" : 100.00% +

+

(25 of 25 relevant lines covered)

+

RouteComposer/Classes/Extensions/Array+Extension.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 01/03/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// - Extension of an `Array` of the `UIViewControllers` is to check if all of them can be dismissed.
9
public extension Array where Element: UIViewController {
10
11
    /// Returns `true` if all `UIViewController` instances can be dismissed.
12
    var canBeDismissed: Bool {
172x
13
        return nonDismissibleViewController == nil
172x
14
    }
172x
15
16
}
17
18
extension Array where Element: UIViewController {
19
20
    var nonDismissibleViewController: UIViewController? {
266x
21
        return compactMap {
372x
22
            $0 as? RoutingInterceptable & UIViewController
372x
23
        }.first {
372x
24
            !$0.canBeDismissed
186x
25
        }
186x
26
    }
266x
27
28
    func uniqueElements() -> [Element] {
553x
29
        return self.reduce(into: [Element](), {
988x
30
            if !$0.contains($1) {
988x
31
                $0.append($1)
719x
32
            }
988x
33
        })
988x
34
    }
553x
35
36
    func isEqual(to array: [UIViewController]) -> Bool {
7x
37
        guard self.count == array.count else {
7x
38
            return false
5x
39
        }
5x
40
        return self.enumerated().first(where: { (index, vc) in
5x
41
            return array[index] !== vc
5x
42
        }) == nil
5x
43
    }
7x
44
45
}
+
+ + + diff --git a/docs/tests/BaseEntitiesCollector.swift.html b/docs/tests/BaseEntitiesCollector.swift.html new file mode 100644 index 000000000..ee3efe64c --- /dev/null +++ b/docs/tests/BaseEntitiesCollector.swift.html @@ -0,0 +1,162 @@ + + + +BaseEntitiesCollector.swift - Slather + + + +
Slather logo
+

+Coverage for "BaseEntitiesCollector.swift" : 100.00% +

+

(11 of 11 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/BaseEntitiesCollector.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-10-31.
3
//
4
5
import Foundation
6
import UIKit
7
8
struct BaseEntitiesCollector<FactoryBoxer: AnyFactoryBox, ActionBoxer: AnyActionBox>: EntitiesProvider {
9
10
    let factory: AnyFactory?
11
12
    let finder: AnyFinder?
13
14
    init<F: Finder>(finder: F, factory: FactoryBoxer.FactoryType, action: ActionBoxer.ActionType)
15
            where
16
            F.ViewController == FactoryBoxer.FactoryType.ViewController, F.Context == FactoryBoxer.FactoryType.Context {
204x
17
        self.finder = FinderBox(finder)
204x
18
204x
19
        if let factoryBox = FactoryBoxer(factory, action: ActionBoxer(action)) {
204x
20
            self.factory = factoryBox
145x
21
        } else if let finderFactory = FinderFactory(finder: finder) {
204x
22
            self.factory = FactoryBox(finderFactory, action: ActionBox(ViewControllerActions.NilAction()))
57x
23
        } else {
204x
24
            self.factory = nil
147x
25
        }
204x
26
    }
204x
27
28
}
+
+ + + diff --git a/docs/tests/BaseStep.swift.html b/docs/tests/BaseStep.swift.html new file mode 100644 index 000000000..2dff65227 --- /dev/null +++ b/docs/tests/BaseStep.swift.html @@ -0,0 +1,437 @@ + + + +BaseStep.swift - Slather + + + +
Slather logo
+

+Coverage for "BaseStep.swift" : 94.12% +

+

(32 of 34 relevant lines covered)

+

RouteComposer/Classes/Router/Internal/BaseStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 23/01/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
protocol EntitiesProvider {
9
10
    var finder: AnyFinder? { get }
11
12
    var factory: AnyFactory? { get }
13
14
}
15
16
protocol TaskProvider {
17
18
    var interceptor: AnyRoutingInterceptor? { get }
19
20
    var contextTask: AnyContextTask? { get }
21
22
    var postTask: AnyPostRoutingTask? { get }
23
}
24
25
struct BaseStep: RoutingStep,
26
        ChainableStep,
27
        InterceptableStep,
28
        PerformableStep,
29
        CustomStringConvertible {
30
31
    private var previousStep: RoutingStep?
32
33
    let factory: AnyFactory?
34
35
    let finder: AnyFinder?
36
37
    let interceptor: AnyRoutingInterceptor?
38
39
    let postTask: AnyPostRoutingTask?
40
41
    let contextTask: AnyContextTask?
42
43
    init(entitiesProvider: EntitiesProvider,
44
         taskProvider: TaskProvider) {
201x
45
        self.finder = entitiesProvider.finder
201x
46
        self.factory = entitiesProvider.factory
201x
47
        self.interceptor = taskProvider.interceptor
201x
48
        self.contextTask = taskProvider.contextTask
201x
49
        self.postTask = taskProvider.postTask
201x
50
    }
201x
51
52
    func getPreviousStep(with context: Any?) -> RoutingStep? {
200x
53
        return previousStep
200x
54
    }
200x
55
56
    func perform(with context: Any?) throws -> PerformableStepResult {
177x
57
        guard let viewController = try finder?.findViewController(with: context) else {
177x
58
            if let factory = factory {
130x
59
                return .build(factory)
130x
60
            } else {
130x
61
                return .none
!
62
            }
!
63
        }
47x
64
        return .success(viewController)
47x
65
    }
177x
66
67
    mutating func from(_ step: RoutingStep) {
189x
68
        previousStep = step
189x
69
    }
189x
70
71
    public var description: String {
142x
72
        var finderDescription = "None"
142x
73
        var factoryDescription = "None"
142x
74
        if let finder = finder {
142x
75
            finderDescription = String(describing: finder)
115x
76
        }
142x
77
        if let factory = factory {
142x
78
            factoryDescription = String(describing: factory)
141x
79
        }
142x
80
        return "BaseStep<\(finderDescription) : \(factoryDescription))>"
142x
81
    }
142x
82
83
}
+
+ + + diff --git a/docs/tests/ChainAssembly.swift.html b/docs/tests/ChainAssembly.swift.html new file mode 100644 index 000000000..173447e8c --- /dev/null +++ b/docs/tests/ChainAssembly.swift.html @@ -0,0 +1,142 @@ + + + +ChainAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "ChainAssembly.swift" : 100.00% +

+

(3 of 3 relevant lines covered)

+

RouteComposer/Classes/Assemblies/ChainAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 07/02/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Builds a chain of steps.
9
public struct ChainAssembly {
10
11
    /// Transforms step into a chain of steps.
12
    /// ### Usage
13
    /// ```swift
14
    /// let intermediateStep = ChainAssembly.from(NavigationControllerStep())
15
    ///         .from(using: GeneralAction.presentModally())
16
    ///         .from(GeneralStep.current())
17
    ///         .assemble()
18
    /// ```
19
    /// - Parameter step: The instance of `ActionConnectingAssembly`
20
    public static func from<VC: UIViewController, C>(_ step: ActionToStepIntegrator<VC, C>) -> ActionConnectingAssembly<VC, VC, C> {
1x
21
        return ActionConnectingAssembly(stepToFullFill: step, previousSteps: [])
1x
22
    }
1x
23
24
}
+
+ + + diff --git a/docs/tests/ChildCoordinator.swift.html b/docs/tests/ChildCoordinator.swift.html new file mode 100644 index 000000000..fbd50262a --- /dev/null +++ b/docs/tests/ChildCoordinator.swift.html @@ -0,0 +1,177 @@ + + + +ChildCoordinator.swift - Slather + + + +
Slather logo
+

+Coverage for "ChildCoordinator.swift" : 100.00% +

+

(10 of 10 relevant lines covered)

+

RouteComposer/Classes/ChildCoordinator.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 07/09/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Helps to build a child view controller stack
9
public struct ChildCoordinator<Context> {
10
11
    var childFactories: [DelayedIntegrationFactory<Context>]
12
13
    init(childFactories: [DelayedIntegrationFactory<Context>]) {
40x
14
        self.childFactories = childFactories
40x
15
    }
40x
16
17
    /// Builds child view controller stack with the context instance provided.
18
    ///
19
    /// - Parameters:
20
    ///   - context: A `Context` instance that is provided to the `Router`.
21
    ///   - existingViewControllers: Current view controller stack of the container.
22
    /// - Returns: Built child view controller stack
23
    public func build(with context: Context, integrating existingViewControllers: [UIViewController] = []) throws -> [UIViewController] {
33x
24
        var childrenViewControllers = existingViewControllers
33x
25
        for factory in childFactories {
49x
26
            try factory.build(with: context, in: &childrenViewControllers)
49x
27
        }
49x
28
        return childrenViewControllers
33x
29
    }
33x
30
31
}
+
+ + + diff --git a/docs/tests/ClassFinder.swift.html b/docs/tests/ClassFinder.swift.html new file mode 100644 index 000000000..2b6dd3d5f --- /dev/null +++ b/docs/tests/ClassFinder.swift.html @@ -0,0 +1,222 @@ + + + +ClassFinder.swift - Slather + + + +
Slather logo
+

+Coverage for "ClassFinder.swift" : 100.00% +

+

(9 of 9 relevant lines covered)

+

RouteComposer/Classes/Finders/ClassFinder.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// A default implementation of the view controllers finder that searches for a view controller by its name.
10
public struct ClassFinder<VC: UIViewController, C>: StackIteratingFinder {
11
12
    /// A `StackIterator` is to be used by `ClassFinder`
13
    public let iterator: StackIterator
14
15
    /// Constructor
16
    ///
17
    /// - Parameter iterator: A `StackIterator` is to be used by `ClassFinder`
18
    public init(iterator: StackIterator = DefaultStackIterator()) {
81x
19
        self.iterator = iterator
81x
20
    }
81x
21
22
    public func isTarget(_ viewController: VC, with context: C) -> Bool {
64x
23
        return true
64x
24
    }
64x
25
26
}
27
28
/// Extension to use `DefaultStackIterator` as default iterator.
29
public extension ClassFinder {
30
31
    /// Constructor
32
    ///
33
    /// Parameters
34
    ///   - options: A combination of the `SearchOptions`
35
    ///   - startingPoint: `DefaultStackIterator.StartingPoint` value
36
    init(options: SearchOptions, startingPoint: DefaultStackIterator.StartingPoint = .topmost) {
59x
37
        self.iterator = DefaultStackIterator(options: options, startingPoint: startingPoint)
59x
38
    }
59x
39
40
}
+
+ + + diff --git a/docs/tests/ClassNameFactory.swift.html b/docs/tests/ClassNameFactory.swift.html new file mode 100644 index 000000000..940db73dc --- /dev/null +++ b/docs/tests/ClassNameFactory.swift.html @@ -0,0 +1,267 @@ + + + +ClassNameFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "ClassNameFactory.swift" : 90.00% +

+

(18 of 20 relevant lines covered)

+

RouteComposer/Classes/Factories/ClassNameFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// The `Factory` that creates a `UIViewController` class by its name
9
public struct ClassNameFactory<VC: UIViewController, C>: Factory {
10
11
    /// The name of a `UIViewController` class to be built by the `Factory`
12
    public let viewControllerName: String?
13
14
    /// A Xib file name
15
    public let nibName: String?
16
17
    /// A `Bundle` instance
18
    public let bundle: Bundle?
19
20
    /// Constructor
21
    ///
22
    /// - Parameters:
23
    ///   - viewControllerName: The name of a `UIViewController` class to be built, if not provided - `ViewController`
24
    ///     type will be used.
25
    ///   - nibName: A Xib file name
26
    ///   - bundle: A `Bundle` instance if needed
27
    public init(viewControllerName: String? = nil, nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
11x
28
        self.viewControllerName = viewControllerName
11x
29
        self.nibName = nibNameOrNil
11x
30
        self.bundle = nibBundleOrNil
11x
31
    }
11x
32
33
    public func build(with context: C) throws -> VC {
8x
34
        if let viewControllerName = viewControllerName {
8x
35
            guard let customClass = NSClassFromString(viewControllerName) else {
3x
36
                throw RoutingError.compositionFailed(.init("Can not find \(viewControllerName) in the bundle."))
!
37
            }
3x
38
            guard let customViewControllerClass = customClass as? VC.Type else {
3x
39
                throw RoutingError.typeMismatch(customClass.self, .init("\(viewControllerName) is not an " +
2x
40
                        "expected UIViewController type class."))
2x
41
            }
2x
42
1x
43
            return customViewControllerClass.init(nibName: nibName, bundle: bundle)
1x
44
        } else {
5x
45
            return ViewController(nibName: nibName, bundle: bundle)
5x
46
        }
5x
47
    }
!
48
49
}
+
+ + + diff --git a/docs/tests/ClassWithContextFinder.swift.html b/docs/tests/ClassWithContextFinder.swift.html new file mode 100644 index 000000000..781fa6e44 --- /dev/null +++ b/docs/tests/ClassWithContextFinder.swift.html @@ -0,0 +1,232 @@ + + + +ClassWithContextFinder.swift - Slather + + + +
Slather logo
+

+Coverage for "ClassWithContextFinder.swift" : 66.67% +

+

(6 of 9 relevant lines covered)

+

RouteComposer/Classes/Finders/ClassWithContextFinder.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 27/02/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// A default implementation of the view controllers finder, that searches for a view controller by its name
9
/// and its `Context` instance.
10
///
11
/// The view controller should conform to the `ContextChecking` to be used with this finder.
12
public struct ClassWithContextFinder<VC: ContextChecking, C>: StackIteratingFinder where VC.Context == C {
13
14
    /// A `StackIterator` is to be used by `ClassWithContextFinder`
15
    public let iterator: StackIterator
16
17
    /// Constructor
18
    ///
19
    /// - Parameter iterator: A `StackIterator` is to be used by `ClassWithContextFinder`
20
    public init(iterator: StackIterator = DefaultStackIterator()) {
4x
21
        self.iterator = iterator
4x
22
    }
4x
23
24
    public func isTarget(_ viewController: VC, with context: C) -> Bool {
1x
25
        return viewController.isTarget(for: context)
1x
26
    }
1x
27
28
}
29
30
/// Extension to use `DefaultStackIterator` as default iterator.
31
public extension ClassWithContextFinder {
32
33
    /// Constructor
34
    ///
35
    /// Parameters
36
    ///   - options: A combination of the `SearchOptions`
37
    ///   - startingPoint: `DefaultStackIterator.StartingPoint` value
38
    init(options: SearchOptions, startingPoint: DefaultStackIterator.StartingPoint = .topmost) {
!
39
        self.iterator = DefaultStackIterator(options: options, startingPoint: startingPoint)
!
40
    }
!
41
42
}
+
+ + + diff --git a/docs/tests/CompleteFactory.swift.html b/docs/tests/CompleteFactory.swift.html new file mode 100644 index 000000000..a4cc6df93 --- /dev/null +++ b/docs/tests/CompleteFactory.swift.html @@ -0,0 +1,237 @@ + + + +CompleteFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "CompleteFactory.swift" : 100.00% +

+

(20 of 20 relevant lines covered)

+

RouteComposer/Classes/Factories/CompleteFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  FinderFactory.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 08/02/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
/// The `CompleteFactory` instance is used by the `CompleteFactoryAssembly` as a `ContainerFactory` to
12
/// pre-populate the children view controllers instead of the `Router`.
13
public struct CompleteFactory<FC: ContainerFactory>: ContainerFactory, CustomStringConvertible {
14
15
    private var factory: FC
16
17
    var childFactories: [DelayedIntegrationFactory<FC.Context>]
18
19
    init(factory: FC, childFactories: [DelayedIntegrationFactory<FC.Context>]) {
7x
20
        self.factory = factory
7x
21
        self.childFactories = childFactories
7x
22
    }
7x
23
24
    mutating public func prepare(with context: FC.Context) throws {
3x
25
        try factory.prepare(with: context)
3x
26
        childFactories = try childFactories.map({
6x
27
            var factory = $0
6x
28
            try factory.prepare(with: context)
6x
29
            return factory
6x
30
        })
6x
31
    }
3x
32
33
    public func build(with context: FC.Context, integrating coordinator: ChildCoordinator<FC.Context>) throws -> FC.ViewController {
5x
34
        var finalChildFactories = childFactories
5x
35
        finalChildFactories.append(contentsOf: coordinator.childFactories)
5x
36
        return try factory.build(with: context, integrating: ChildCoordinator(childFactories: finalChildFactories))
5x
37
    }
5x
38
39
    public var description: String {
1x
40
        return String(describing: factory)
1x
41
    }
1x
42
43
}
+
+ + + diff --git a/docs/tests/CompleteFactoryAssembly.swift.html b/docs/tests/CompleteFactoryAssembly.swift.html new file mode 100644 index 000000000..2196bb073 --- /dev/null +++ b/docs/tests/CompleteFactoryAssembly.swift.html @@ -0,0 +1,562 @@ + + + +CompleteFactoryAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "CompleteFactoryAssembly.swift" : 39.13% +

+

(18 of 46 relevant lines covered)

+

RouteComposer/Classes/Assemblies/CompleteFactoryAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 16/03/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Builds a `ContainerFactory` fulfilled with the children `UIViewController` factories.
9
///
10
/// ```swift
11
/// let rootFactory = CompleteFactoryAssembly(factory: TabBarFactory())
12
///         .with(XibFactory<HomeViewController, Any?>, using: UITabBarController.add())
13
///         .with(XibFactory<AccountViewController, Any?>, using: UITabBarController.add())
14
///         .assemble()
15
/// ```
16
/// *NB: Order matters here*
17
public final class CompleteFactoryAssembly<FC: ContainerFactory> {
18
19
    struct AddAction<FC: ContainerFactory>: ContainerAction {
20
21
        func perform(with viewController: UIViewController, on existingController: FC.ViewController, animated: Bool, completion: @escaping (ActionResult) -> Void) {
!
22
            assertionFailure("Should never be called")
!
23
        }
!
24
25
        func perform(embedding viewController: UIViewController, in childViewControllers: inout [UIViewController]) {
2x
26
            childViewControllers.append(viewController)
2x
27
        }
2x
28
29
    }
30
31
    private var factory: FC
32
33
    /// Constructor
34
    ///
35
    /// - Parameters:
36
    ///   - factory: The `ContainerFactory` instance.
37
    public init(factory: FC) {
3x
38
        self.factory = factory
3x
39
    }
3x
40
41
    /// Adds a `Factory` that is going to be used as a child
42
    ///
43
    /// - Parameters:
44
    ///   - childFactory: The instance of `Factory`.
45
    ///   - action: The instance of `Factory` to be used to integrate the view controller produced by the factory.
46
    public func with<ChildFC: Factory, A: ContainerAction>(_ childFactory: ChildFC, using action: A) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController>
47
            where
48
            ChildFC.Context == FC.Context, A.ViewController == FC.ViewController {
1x
49
        guard let factoryBox = FactoryBox(childFactory, action: ContainerActionBox(action)) else {
1x
50
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory, childFactories: [], previousChildFactory: nil)
1x
51
        }
1x
52
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory,
!
53
                childFactories: [],
!
54
                previousChildFactory: DelayedIntegrationFactory<ChildFC.Context>(factoryBox))
!
55
    }
1x
56
57
    /// Adds a `ContainerFactory` that is going to be used as a child
58
    ///
59
    /// - Parameters:
60
    ///   - childFactory: The instance of `ContainerFactory`.
61
    ///   - action: The instance of `ContainerFactory` to be used to integrate the view controller produced by the factory.
62
    public func with<ChildFC: ContainerFactory, A: ContainerAction>(_ childContainer: ChildFC, using action: A) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController>
63
            where
64
            ChildFC.Context == FC.Context, A.ViewController == FC.ViewController {
!
65
        guard let factoryBox = ContainerFactoryBox(childContainer, action: ContainerActionBox(action)) else {
!
66
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory, childFactories: [], previousChildFactory: nil)
!
67
        }
!
68
!
69
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory,
!
70
                childFactories: [],
!
71
                previousChildFactory: DelayedIntegrationFactory<ChildFC.Context>(factoryBox))
!
72
    }
!
73
74
    /// Adds a `Factory` as the last view controller in the stack.
75
    ///
76
    /// - Parameters:
77
    ///   - childFactory: The instance of `Factory`.
78
    public func with<ChildFC: Factory>(_ childFactory: ChildFC) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController> where ChildFC.Context == FC.Context {
2x
79
        guard let factoryBox = FactoryBox(childFactory, action: ContainerActionBox(AddAction<FC>())) else {
2x
80
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory, childFactories: [], previousChildFactory: nil)
!
81
        }
2x
82
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory,
2x
83
                childFactories: [],
2x
84
                previousChildFactory: DelayedIntegrationFactory<ChildFC.Context>(factoryBox))
2x
85
    }
2x
86
87
    /// Adds a `ContainerFactory` as the last view controller in the stack.
88
    ///
89
    /// - Parameters:
90
    ///   - childFactory: The instance of `ContainerFactory`.
91
    public func with<ChildFC: ContainerFactory>(_ childContainer: ChildFC) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController> where ChildFC.Context == FC.Context {
!
92
        guard let factoryBox = ContainerFactoryBox(childContainer, action: ContainerActionBox(AddAction<FC>())) else {
!
93
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory, childFactories: [], previousChildFactory: nil)
!
94
        }
!
95
!
96
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory,
!
97
                childFactories: [],
!
98
                previousChildFactory: DelayedIntegrationFactory<ChildFC.Context>(factoryBox))
!
99
    }
!
100
101
    /// Assembles all the children factories provided and returns a `ContainerFactory` instance.
102
    ///
103
    /// - Returns: The `CompleteFactory` with child factories provided.
104
    public func assemble() -> CompleteFactory<FC> {
!
105
        return CompleteFactory<FC>(factory: factory, childFactories: [])
!
106
    }
!
107
108
}
+
+ + + diff --git a/docs/tests/CompleteFactoryChainAssembly.swift.html b/docs/tests/CompleteFactoryChainAssembly.swift.html new file mode 100644 index 000000000..b09cdc020 --- /dev/null +++ b/docs/tests/CompleteFactoryChainAssembly.swift.html @@ -0,0 +1,582 @@ + + + +CompleteFactoryChainAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "CompleteFactoryChainAssembly.swift" : 67.24% +

+

(39 of 58 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/CompleteFactoryChainAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-04-04.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Builds the chain of assemblies to fulfill the `ContainerFactory`.
9
public final class CompleteFactoryChainAssembly<FC: ContainerFactory, ChildVC: UIViewController> {
10
11
    private var factory: FC
12
13
    private let childFactories: [DelayedIntegrationFactory<FC.Context>]
14
15
    private let previousChildFactory: DelayedIntegrationFactory<FC.Context>?
16
17
    private var integratedChildFactories: [DelayedIntegrationFactory<FC.Context>] {
6x
18
        var childFactories = self.childFactories
6x
19
        if let previousChildFactory = previousChildFactory {
6x
20
            childFactories.append(previousChildFactory)
4x
21
        }
6x
22
        return childFactories
6x
23
    }
6x
24
25
    init(factory: FC, childFactories: [DelayedIntegrationFactory<FC.Context>], previousChildFactory: DelayedIntegrationFactory<FC.Context>?) {
9x
26
        self.factory = factory
9x
27
        self.childFactories = childFactories
9x
28
        self.previousChildFactory = previousChildFactory
9x
29
    }
9x
30
31
    /// Adds a `Factory` that is going to be used as a child
32
    ///
33
    /// - Parameters:
34
    ///   - childFactory: The instance of `Factory`.
35
    ///   - action: The instance of `Factory` to be used to integrate the view controller produced by the factory.
36
    public func with<ChildFC: Factory, A: ContainerAction>(_ childFactory: ChildFC, using action: A) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController>
37
            where
38
            ChildFC.Context == FC.Context, A.ViewController == FC.ViewController {
2x
39
        guard let factoryBox = FactoryBox(childFactory, action: ContainerActionBox(action)) else {
2x
40
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory, childFactories: integratedChildFactories, previousChildFactory: nil)
1x
41
        }
1x
42
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory,
1x
43
                childFactories: integratedChildFactories,
1x
44
                previousChildFactory: DelayedIntegrationFactory<ChildFC.Context>(factoryBox))
1x
45
    }
2x
46
47
    /// Adds a `ContainerFactory` that is going to be used as a child
48
    ///
49
    /// - Parameters:
50
    ///   - childFactory: The instance of `ContainerFactory`.
51
    ///   - action: The instance of `ContainerFactory` to be used to integrate the view controller produced by the factory.
52
    public func with<ChildFC: ContainerFactory, A: ContainerAction>(_ childContainer: ChildFC, using action: A) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController>
53
            where
54
            ChildFC.Context == FC.Context, A.ViewController == FC.ViewController {
1x
55
        guard let factoryBox = ContainerFactoryBox(childContainer, action: ContainerActionBox(action)) else {
1x
56
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory, childFactories: integratedChildFactories, previousChildFactory: nil)
!
57
        }
1x
58
1x
59
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory,
1x
60
                childFactories: integratedChildFactories,
1x
61
                previousChildFactory: DelayedIntegrationFactory<ChildFC.Context>(factoryBox))
1x
62
    }
1x
63
64
    /// Adds a `Factory` as the last view controller in the stack.
65
    ///
66
    /// - Parameters:
67
    ///   - childFactory: The instance of `Factory`.
68
    public func with<ChildFC: Factory>(_ childFactory: ChildFC) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController> where ChildFC.Context == FC.Context {
!
69
        guard let factoryBox = FactoryBox(childFactory, action: ContainerActionBox(CompleteFactoryAssembly<FC>.AddAction<FC>())) else {
!
70
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory, childFactories: integratedChildFactories, previousChildFactory: nil)
!
71
        }
!
72
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory,
!
73
                childFactories: integratedChildFactories,
!
74
                previousChildFactory: DelayedIntegrationFactory<ChildFC.Context>(factoryBox))
!
75
    }
!
76
77
    /// Adds a `ContainerFactory` as the last view controller in the stack.
78
    ///
79
    /// - Parameters:
80
    ///   - childFactory: The instance of `ContainerFactory`.
81
    public func with<ChildFC: ContainerFactory>(_ childContainer: ChildFC) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController> where ChildFC.Context == FC.Context {
!
82
        guard let factoryBox = ContainerFactoryBox(childContainer, action: ContainerActionBox(CompleteFactoryAssembly<FC>.AddAction<FC>())) else {
!
83
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory, childFactories: integratedChildFactories, previousChildFactory: nil)
!
84
        }
!
85
!
86
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController>(factory: factory,
!
87
                childFactories: integratedChildFactories,
!
88
                previousChildFactory: DelayedIntegrationFactory<ChildFC.Context>(factoryBox))
!
89
    }
!
90
91
    /// Applies a `ContextTask` to the child factory after its `UIViewController` been built.
92
    ///
93
    /// - Parameters:
94
    ///   - contextTask: The instance of `ContextTask`.
95
    public func adding<CT: ContextTask>(_ contextTask: CT) -> CompleteFactoryChainAssembly<FC, ChildVC> where CT.ViewController == ChildVC, CT.Context == FC.Context {
3x
96
        guard var previousChildFactory = previousChildFactory else {
3x
97
            return CompleteFactoryChainAssembly<FC, ChildVC>(factory: factory, childFactories: childFactories, previousChildFactory: nil)
!
98
        }
3x
99
        previousChildFactory.add(ContextTaskBox(contextTask))
3x
100
        return CompleteFactoryChainAssembly<FC, ChildVC>(factory: factory,
3x
101
                childFactories: childFactories,
3x
102
                previousChildFactory: previousChildFactory)
3x
103
    }
3x
104
105
    /// Assembles all the children factories provided and returns a `ContainerFactory` instance.
106
    ///
107
    /// - Returns: The `CompleteFactory` with child factories provided.
108
    public func assemble() -> CompleteFactory<FC> {
3x
109
        return CompleteFactory<FC>(factory: factory, childFactories: integratedChildFactories)
3x
110
    }
3x
111
112
}
+
+ + + diff --git a/docs/tests/ContainerActionBox.swift.html b/docs/tests/ContainerActionBox.swift.html new file mode 100644 index 000000000..f6d892ac7 --- /dev/null +++ b/docs/tests/ContainerActionBox.swift.html @@ -0,0 +1,422 @@ + + + +ContainerActionBox.swift - Slather + + + +
Slather logo
+

+Coverage for "ContainerActionBox.swift" : 77.59% +

+

(45 of 58 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/ContainerActionBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
struct ContainerActionBox<A: ContainerAction>: AnyAction, AnyActionBox, CustomStringConvertible, MainThreadChecking {
8
9
    let action: A
10
11
    init(_ action: A) {
92x
12
        self.action = action
92x
13
    }
92x
14
15
    func perform(with viewController: UIViewController,
16
                 on existingController: UIViewController,
17
                 with delayedIntegrationHandler: DelayedActionIntegrationHandler,
18
                 nextAction: AnyAction?,
19
                 animated: Bool,
20
                 completion: @escaping (ActionResult) -> Void) {
20x
21
        assertIfNotMainThread()
20x
22
        if let delayedController = delayedIntegrationHandler.containerViewController {
20x
23
            guard delayedController is A.ViewController else {
1x
24
                delayedIntegrationHandler.purge(animated: animated, completion: {
!
25
                    self.perform(with: viewController,
!
26
                            on: existingController,
!
27
                            with: delayedIntegrationHandler,
!
28
                            nextAction: nextAction,
!
29
                            animated: animated,
!
30
                            completion: completion)
!
31
                })
!
32
                return
!
33
            }
1x
34
            embed(viewController: viewController, with: delayedIntegrationHandler, completion: completion)
1x
35
        } else {
20x
36
            guard let containerController: A.ViewController = UIViewController.findContainer(of: existingController) else {
19x
37
                completion(.failure(RoutingError.typeMismatch(ActionType.ViewController.self, .init("Container of " +
!
38
                        "\(String(describing: ActionType.ViewController.self)) type cannot be found to perform \(action)"))))
!
39
                return
!
40
            }
19x
41
            let shouldDelayPerforming = nextAction?.isEmbeddable(to: A.ViewController.self) ?? false
19x
42
            if shouldDelayPerforming {
19x
43
                delayedIntegrationHandler.update(containerViewController: containerController, animated: animated, completion: {
2x
44
                    self.embed(viewController: viewController, with: delayedIntegrationHandler, completion: completion)
2x
45
                })
2x
46
            } else {
19x
47
                delayedIntegrationHandler.purge(animated: animated, completion: {
17x
48
                    self.action.perform(with: viewController, on: containerController, animated: animated) { result in
17x
49
                        self.assertIfNotMainThread()
16x
50
                        completion(result)
16x
51
                    }
16x
52
                })
17x
53
            }
19x
54
        }
20x
55
    }
20x
56
57
    private func embed(viewController: UIViewController, with delayedIntegrationHandler: DelayedActionIntegrationHandler, completion: @escaping (ActionResult) -> Void) {
3x
58
        do {
3x
59
            var delayedChildControllers = delayedIntegrationHandler.delayedViewControllers
3x
60
            try perform(embedding: viewController, in: &delayedChildControllers)
3x
61
            delayedIntegrationHandler.update(delayedViewControllers: delayedChildControllers)
3x
62
            completion(.continueRouting)
3x
63
        } catch let error {
3x
64
            completion(.failure(error))
!
65
        }
3x
66
    }
3x
67
68
    func perform(embedding viewController: UIViewController, in childViewControllers: inout [UIViewController]) throws {
54x
69
        try action.perform(embedding: viewController, in: &childViewControllers)
54x
70
    }
54x
71
72
    public var description: String {
17x
73
        return String(describing: action)
17x
74
    }
17x
75
76
    func isEmbeddable(to container: ContainerViewController.Type) -> Bool {
38x
77
        return container is A.ViewController.Type
38x
78
    }
38x
79
80
}
+
+ + + diff --git a/docs/tests/ContainerFactory.swift.html b/docs/tests/ContainerFactory.swift.html new file mode 100644 index 000000000..ad3f0260c --- /dev/null +++ b/docs/tests/ContainerFactory.swift.html @@ -0,0 +1,457 @@ + + + +ContainerFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "ContainerFactory.swift" : 69.23% +

+

(18 of 26 relevant lines covered)

+

RouteComposer/Classes/ContainerFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// The `ContainerFactory` protocol should be implemented by the instance that produces any types of the view controllers
10
/// that can be considered as containers (eg: `UINavigationController`, `UITabBarController`, etc)
11
///
12
/// The `Router` uses `ContainerAction.perform(...)` method of a `ContainerAction` and then populates a full stack of the view controllers
13
/// that were built by the associated factories in one go.
14
/// Example: `Router` requires to populate N-view controllers into `UINavigationController`'s stack.
15
public protocol ContainerFactory: AbstractFactory where ViewController: ContainerViewController {
16
17
    /// Type of `UIViewController` that `ContainerFactory` can build
18
    associatedtype ViewController
19
20
    /// `Context` to be passed into `UIViewController`
21
    associatedtype Context
22
23
    /// Builds a `UIViewController` that will be integrated into the stack
24
    ///
25
    /// Parameters:
26
    ///   - context: A `Context` instance that is provided to the `Router`.
27
    ///   - coordinator: A `ChildCoordinator` instance.
28
    /// - Returns: The built `UIViewController` instance with the children view controller inside.
29
    /// - Throws: The `RoutingError` if build did not succeed.
30
    func build(with context: Context, integrating coordinator: ChildCoordinator<Context>) throws -> ViewController
31
32
}
33
34
/// Default implementation
35
public extension ContainerFactory {
36
37
    /// Default implementation does nothing
38
    mutating func prepare(with context: Context) throws {
26x
39
    }
26x
40
41
    /// Builds a `ContainerFactory` view controller.
42
    func build(with context: Context) throws -> ViewController {
6x
43
        return try build(with: context, integrating: ChildCoordinator(childFactories: []))
6x
44
    }
6x
45
46
    /// Prepares the `Factory` and builds a `UIViewController`
47
    func buildPrepared(with context: Context) throws -> ViewController {
1x
48
        var factory = self
1x
49
        try factory.prepare(with: context)
1x
50
        return try factory.build(with: context)
1x
51
    }
1x
52
53
}
54
55
/// Default implementation for any context
56
public extension ContainerFactory where Context == Any? {
57
58
    /// Builds a `ContainerFactory` view controller.
59
    func build() throws -> ViewController {
2x
60
        return try build(with: nil)
2x
61
    }
2x
62
63
    /// Prepares the `Factory` and builds a `UIViewController`
64
    func buildPrepared() throws -> ViewController {
2x
65
        var factory = self
2x
66
        try factory.prepare()
2x
67
        return try factory.build()
2x
68
    }
2x
69
70
}
71
72
/// Default implementation for an empty context
73
public extension ContainerFactory where Context == Void {
74
75
    /// Builds a `ContainerFactory` view controller.
76
    func build() throws -> ViewController {
!
77
        return try build(with: ())
!
78
    }
!
79
80
    /// Prepares the `Factory` and builds a `UIViewController`
81
    func buildPrepared() throws -> ViewController {
!
82
        var factory = self
!
83
        try factory.prepare()
!
84
        return try factory.build()
!
85
    }
!
86
87
}
+
+ + + diff --git a/docs/tests/ContainerFactoryBox.swift.html b/docs/tests/ContainerFactoryBox.swift.html new file mode 100644 index 000000000..c56c22f2e --- /dev/null +++ b/docs/tests/ContainerFactoryBox.swift.html @@ -0,0 +1,277 @@ + + + +ContainerFactoryBox.swift - Slather + + + +
Slather logo
+

+Coverage for "ContainerFactoryBox.swift" : 89.66% +

+

(26 of 29 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/ContainerFactoryBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
struct ContainerFactoryBox<F: ContainerFactory>: PreparableAnyFactory, AnyFactoryBox, MainThreadChecking, CustomStringConvertible {
8
9
    typealias FactoryType = F
10
11
    var factory: FactoryType
12
13
    let action: AnyAction
14
15
    var children: [DelayedIntegrationFactory<FactoryType.Context>] = []
16
17
    var isPrepared = false
18
19
    init?(_ factory: FactoryType, action: AnyAction) {
42x
20
        guard !(factory is NilEntity) else {
42x
21
            return nil
!
22
        }
42x
23
        self.factory = factory
42x
24
        self.action = action
42x
25
    }
42x
26
27
    mutating func scrapeChildren(from factories: [AnyFactory]) throws -> [AnyFactory] {
25x
28
        var otherFactories: [AnyFactory] = []
25x
29
        var isNonEmbeddableFound = false
25x
30
        self.children = factories.compactMap({ child -> DelayedIntegrationFactory<FactoryType.Context>? in
41x
31
            guard !isNonEmbeddableFound, child.action.isEmbeddable(to: FactoryType.ViewController.self) else {
41x
32
                otherFactories.append(child)
8x
33
                isNonEmbeddableFound = true
8x
34
                return nil
8x
35
            }
33x
36
            return DelayedIntegrationFactory(child)
33x
37
        })
41x
38
        return otherFactories
25x
39
    }
25x
40
41
    func build(with context: Any?) throws -> UIViewController {
24x
42
        guard let typedContext = Any?.some(context as Any) as? FactoryType.Context else {
24x
43
            throw RoutingError.typeMismatch(FactoryType.Context.self, .init("\(String(describing: factory.self)) does " +
!
44
                    "not accept \(String(describing: context.self)) as a context."))
!
45
        }
24x
46
        assertIfNotMainThread()
24x
47
        assertIfNotPrepared()
24x
48
        return try factory.build(with: typedContext, integrating: ChildCoordinator(childFactories: children))
24x
49
    }
24x
50
51
}
+
+ + + diff --git a/docs/tests/ContainerStepAssembly.swift.html b/docs/tests/ContainerStepAssembly.swift.html new file mode 100644 index 000000000..c02c7dccc --- /dev/null +++ b/docs/tests/ContainerStepAssembly.swift.html @@ -0,0 +1,472 @@ + + + +ContainerStepAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "ContainerStepAssembly.swift" : 55.88% +

+

(19 of 34 relevant lines covered)

+

RouteComposer/Classes/Assemblies/ContainerStepAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 31/08/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Builds a `DestinationStep` instance with the correct settings into a chain of steps.
9
/// ### NB:
10
/// Both `Finder` and `Factory` instances should deal with the same type of `UIViewController` and `Context` instances.
11
/// ### Usage
12
/// ```swift
13
/// let containerScreen = ContainerStepAssembly(finder: ClassFinder(), factory: NavigationControllerFactory())
14
///         .using(GeneralAction.presentModally())
15
///         .from(GeneralAction.current())
16
///         .assemble()
17
/// ```
18
public final class ContainerStepAssembly<F: Finder, FC: ContainerFactory>: GenericStepAssembly<F.ViewController, F.Context>, ActionConnecting
19
        where
20
        F.ViewController == FC.ViewController, F.Context == FC.Context {
21
22
    let finder: F
23
24
    let factory: FC
25
26
    let previousSteps: [RoutingStep]
27
28
    /// Constructor
29
    ///
30
    /// - Parameters:
31
    ///   - finder: The `UIViewController` `Finder` instance.
32
    ///   - factory: The `UIViewController` `ContainerFactory` instance.
33
    public init(finder: F, factory: FC) {
3x
34
        self.factory = factory
3x
35
        self.finder = finder
3x
36
        self.previousSteps = []
3x
37
    }
3x
38
39
    /// Connects previously provided `DestinationStep` instance with an `Action`
40
    ///
41
    /// - Parameter action: `Action` instance to be used with a step.
42
    public func using<A: Action>(_ action: A) -> StepChainAssembly<ViewController, Context> {
1x
43
        var previousSteps = self.previousSteps
1x
44
        let entitiesCollector = BaseEntitiesCollector<ContainerFactoryBox<FC>, ActionBox>(finder: finder, factory: factory, action: action)
1x
45
        let step = BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
1x
46
        previousSteps.append(step)
1x
47
        return StepChainAssembly(previousSteps: previousSteps)
1x
48
    }
1x
49
50
    /// Connects previously provided `DestinationStep` instance with an `Action`
51
    ///
52
    /// - Parameter action: `ContainerAction` instance to be used with a step.
53
    public func using<A: ContainerAction>(_ action: A) -> ContainerStepChainAssembly<A.ViewController, ViewController, Context> {
2x
54
        var previousSteps = self.previousSteps
2x
55
        let entitiesCollector = BaseEntitiesCollector<ContainerFactoryBox<FC>, ContainerActionBox>(finder: finder, factory: factory, action: action)
2x
56
        let step = BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
2x
57
        previousSteps.append(step)
2x
58
        return ContainerStepChainAssembly(previousSteps: previousSteps)
2x
59
    }
2x
60
61
}
62
63
public extension ContainerStepAssembly where FC: NilEntity {
64
65
    /// Connects previously provided `ActionToStepIntegrator` with `NilEntity` factory with a step where the `UIViewController`
66
    /// should avoid type checks.
67
    ///
68
    /// - Parameter step: `ActionToStepIntegrator` instance to be used.
69
    func from<VC: UIViewController>(_ step: ActionToStepIntegrator<VC, Context>) -> ActionConnectingAssembly<VC, ViewController, Context> {
!
70
        var previousSteps = self.previousSteps
!
71
        let entitiesCollector = BaseEntitiesCollector<ContainerFactoryBox<FC>, ActionBox>(finder: finder, factory: factory, action: ViewControllerActions.NilAction())
!
72
        let currentStep = BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
!
73
        previousSteps.append(currentStep)
!
74
        return ActionConnectingAssembly(stepToFullFill: step, previousSteps: previousSteps)
!
75
    }
!
76
77
    /// Connects previously provided `DestinationStep` with `NilEntity` factory with a step where the `UIViewController`
78
    /// should avoid type checks
79
    ///
80
    /// - Parameter step: `DestinationStep` instance to be used.
81
    func from<VC: UIViewController>(_ step: DestinationStep<VC, Context>) -> LastStepInChainAssembly<ViewController, Context> {
!
82
        var previousSteps = self.previousSteps
!
83
        let entitiesCollector = BaseEntitiesCollector<ContainerFactoryBox<FC>, ActionBox>(finder: finder, factory: factory, action: ViewControllerActions.NilAction())
!
84
        let currentStep = BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
!
85
        previousSteps.append(currentStep)
!
86
        previousSteps.append(step)
!
87
        return LastStepInChainAssembly(previousSteps: previousSteps)
!
88
    }
!
89
90
}
+
+ + + diff --git a/docs/tests/ContainerStepChainAssembly.swift.html b/docs/tests/ContainerStepChainAssembly.swift.html new file mode 100644 index 000000000..31b3c2cf5 --- /dev/null +++ b/docs/tests/ContainerStepChainAssembly.swift.html @@ -0,0 +1,237 @@ + + + +ContainerStepChainAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "ContainerStepChainAssembly.swift" : 100.00% +

+

(16 of 16 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/ContainerStepChainAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Helper class to build a chain of steps. Can not be used directly.
9
public struct ContainerStepChainAssembly<AcceptableContainer: ContainerViewController, ViewController: UIViewController, Context> {
10
11
    let previousSteps: [RoutingStep]
12
13
    init(previousSteps: [RoutingStep]) {
58x
14
        self.previousSteps = previousSteps
58x
15
    }
58x
16
17
    /// Adds a single step to the chain
18
    ///
19
    /// - Parameter previousStep: The instance of `StepWithActionAssemblable`
20
    public func from(_ step: ActionToStepIntegrator<AcceptableContainer, Context>) -> ActionConnectingAssembly<AcceptableContainer, ViewController, Context> {
33x
21
        return ActionConnectingAssembly<AcceptableContainer, ViewController, Context>(stepToFullFill: step, previousSteps: previousSteps)
33x
22
    }
33x
23
24
    /// Adds a `DestinationStep` to the chain. This step will be the last one in the chain.
25
    ///
26
    /// - Parameter previousStep: The instance of `DestinationStep`
27
    public func from(_ step: DestinationStep<AcceptableContainer, Context>) -> LastStepInChainAssembly<ViewController, Context> {
24x
28
        var previousSteps = self.previousSteps
24x
29
        previousSteps.append(step)
24x
30
        return LastStepInChainAssembly(previousSteps: previousSteps)
24x
31
    }
24x
32
33
    /// Assembles all the provided settings.
34
    ///
35
    /// - Parameter step: An instance of `DestinationStep` to build a current stack from.
36
    /// - Returns: An instance of `DestinationStep` with all the provided settings inside.
37
    public func assemble(from step: DestinationStep<AcceptableContainer, Context>) -> DestinationStep<ViewController, Context> {
1x
38
        var previousSteps = self.previousSteps
1x
39
        previousSteps.append(step)
1x
40
        return LastStepInChainAssembly(previousSteps: previousSteps).assemble()
1x
41
    }
1x
42
43
}
+
+ + + diff --git a/docs/tests/ContextAccepting.swift.html b/docs/tests/ContextAccepting.swift.html new file mode 100644 index 000000000..5f435ba11 --- /dev/null +++ b/docs/tests/ContextAccepting.swift.html @@ -0,0 +1,207 @@ + + + +ContextAccepting.swift - Slather + + + +
Slather logo
+

+Coverage for "ContextAccepting.swift" : 0.00% +

+

(0 of 2 relevant lines covered)

+

RouteComposer/Classes/Extra/ContextAccepting.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-03-15.
3
// Copyright © 2019 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// The protocol for `UIViewController`'s to make it compatible with `ContextSettingTask`.
10
public protocol ContextAccepting where Self: UIViewController {
11
12
    /// Type of `Context` object that `UIViewController` can deal with
13
    associatedtype Context
14
15
    /// `ContextSettingTask` will call this method to provide the `Context` instance to the `UIViewController`
16
    /// that has just been build or found.
17
    ///
18
    /// - Parameter context: `Context` instance.
19
    /// - Throws: throws `Error` if `Context` instance is not supported. `Router` will stop building the rest of the stack in this case.
20
    func setup(with context: Context) throws
21
22
    /// If `UIViewController` does not support all the permutations that context instance may have -
23
    /// setup the check here.
24
    ///
25
    /// - Parameter context: `Context` instance.
26
    /// - Throws: throws `Error` if `Context` instance is not supported.
27
    static func checkCompatibility(with context: Context) throws
28
29
}
30
31
public extension ContextAccepting {
32
33
    /// Default implementation does nothing.
34
    static func checkCompatibility(with context: Context) throws {
!
35
    }
!
36
37
}
+
+ + + diff --git a/docs/tests/ContextSettingTask.swift.html b/docs/tests/ContextSettingTask.swift.html new file mode 100644 index 000000000..676a7bad5 --- /dev/null +++ b/docs/tests/ContextSettingTask.swift.html @@ -0,0 +1,142 @@ + + + +ContextSettingTask.swift - Slather + + + +
Slather logo
+

+Coverage for "ContextSettingTask.swift" : 100.00% +

+

(8 of 8 relevant lines covered)

+

RouteComposer/Classes/Extra/ContextSettingTask.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-03-15.
3
// Copyright © 2019 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// `ContextTask` that simplifies setting of the context to the `UIViewController` that implements `ContextAccepting` protocol.
10
public struct ContextSettingTask<VC: ContextAccepting>: ContextTask {
11
12
    /// Constructor
13
    public init() {
5x
14
    }
5x
15
16
    public func prepare(with context: VC.Context) throws {
8x
17
        try VC.checkCompatibility(with: context)
8x
18
    }
8x
19
20
    public func apply(on viewController: VC, with context: VC.Context) throws {
7x
21
        try viewController.setup(with: context)
7x
22
    }
7x
23
24
}
+
+ + + diff --git a/docs/tests/ContextTask.swift.html b/docs/tests/ContextTask.swift.html new file mode 100644 index 000000000..a6fb83c10 --- /dev/null +++ b/docs/tests/ContextTask.swift.html @@ -0,0 +1,457 @@ + + + +ContextTask.swift - Slather + + + +
Slather logo
+

+Coverage for "ContextTask.swift" : 20.00% +

+

(3 of 15 relevant lines covered)

+

RouteComposer/Classes/ContextTask.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  ContextTask.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 27/02/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
/// The task to be applied after a `UIViewController` was created or found.
12
public protocol ContextTask {
13
14
    /// A`UIViewController` type associated with this `ContextTask`
15
    associatedtype ViewController: UIViewController
16
17
    /// A Context type associated with this `ContextTask`
18
    associatedtype Context
19
20
    /// The `Router` will call this method before the navigation process. If the `ContextTask` is not able to
21
    /// be applied to a view controller it should throw an exception.
22
    ///
23
    /// - Parameters:
24
    ///   - context: The `Context` instance provided to the `Router`
25
    /// - Throws: The `RoutingError` if `ContextTask` can't be applied.
26
    mutating func prepare(with context: Context) throws
27
28
    /// The method that will be called by the `Router` to run `ContextTask` immediately after `UIViewController` been created
29
    /// or found
30
    ///
31
    /// - Parameters:
32
    ///   - viewController: The `UIViewController` instance described in the step that `ContextTask` attached to
33
    ///   - context: The `Context` instance that was passed to the `Router`
34
    func apply(on viewController: ViewController, with context: Context) throws
35
36
}
37
38
public extension ContextTask {
39
40
    /// Default implementation does nothing
41
    mutating func prepare(with context: Context) throws {
91x
42
91x
43
    }
91x
44
45
}
46
47
public extension ContextTask where Context == Any? {
48
49
    /// The `Router` will call this method before the navigation process. If the `ContextTask` is not able to
50
    /// be applied to a view controller it should throw an exception.
51
    ///
52
    /// - Throws: The `RoutingError` if `ContextTask` can't be applied.
53
    mutating func prepare() throws {
!
54
        try prepare(with: nil)
!
55
    }
!
56
57
    /// The method that will be called by the `Router` to run `ContextTask` immediately after `UIViewController` been created
58
    /// or found
59
    ///
60
    /// - Parameters:
61
    ///   - viewController: The `UIViewController` instance described in the step that `ContextTask` attached to
62
    func apply(on viewController: ViewController) throws {
!
63
        try apply(on: viewController, with: nil)
!
64
    }
!
65
66
}
67
68
public extension ContextTask where Context == Void {
69
70
    /// The `Router` will call this method before the navigation process. If the `ContextTask` is not able to
71
    /// be applied to a view controller it should throw an exception.
72
    ///
73
    /// - Throws: The `RoutingError` if `ContextTask` can't be applied.
74
    mutating func prepare() throws {
!
75
        try prepare(with: ())
!
76
    }
!
77
78
    /// The method that will be called by the `Router` to run `ContextTask` immediately after `UIViewController` been created
79
    /// or found
80
    ///
81
    /// - Parameters:
82
    ///   - viewController: The `UIViewController` instance described in the step that `ContextTask` attached to
83
    func apply(on viewController: ViewController) throws {
!
84
        try apply(on: viewController, with: ())
!
85
    }
!
86
87
}
+
+ + + diff --git a/docs/tests/ContextTaskBox.swift.html b/docs/tests/ContextTaskBox.swift.html new file mode 100644 index 000000000..352999a9f --- /dev/null +++ b/docs/tests/ContextTaskBox.swift.html @@ -0,0 +1,227 @@ + + + +ContextTaskBox.swift - Slather + + + +
Slather logo
+

+Coverage for "ContextTaskBox.swift" : 91.67% +

+

(22 of 24 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/ContextTaskBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
struct ContextTaskBox<CT: ContextTask>: AnyContextTask, PreparableEntity, MainThreadChecking, CustomStringConvertible {
8
9
    var contextTask: CT
10
11
    var isPrepared = false
12
13
    init(_ contextTask: CT) {
96x
14
        self.contextTask = contextTask
96x
15
    }
96x
16
17
    mutating func prepare(with context: Any?) throws {
102x
18
        guard let typedContext = Any?.some(context as Any) as? CT.Context else {
102x
19
            throw RoutingError.typeMismatch(CT.Context.self, .init("\(String(describing: contextTask.self)) does not " +
!
20
                    "accept \(String(describing: context.self)) as a context."))
!
21
        }
102x
22
        try contextTask.prepare(with: typedContext)
102x
23
        isPrepared = true
102x
24
    }
102x
25
26
    func apply(on viewController: UIViewController, with context: Any?) throws {
100x
27
        guard let typedViewController = viewController as? CT.ViewController,
100x
28
              let typedContext = Any?.some(context as Any) as? CT.Context else {
100x
29
            throw RoutingError.typeMismatch(CT.Context.self, .init("\(String(describing: contextTask.self)) does not " +
1x
30
                    "accept \(String(describing: context.self)) as a context."))
1x
31
        }
99x
32
        assertIfNotMainThread()
99x
33
        assertIfNotPrepared()
99x
34
        try contextTask.apply(on: typedViewController, with: typedContext)
99x
35
    }
99x
36
37
    var description: String {
1x
38
        return String(describing: contextTask)
1x
39
    }
1x
40
41
}
+
+ + + diff --git a/docs/tests/ContextTaskMultiplexer.swift.html b/docs/tests/ContextTaskMultiplexer.swift.html new file mode 100644 index 000000000..1f465ae6a --- /dev/null +++ b/docs/tests/ContextTaskMultiplexer.swift.html @@ -0,0 +1,197 @@ + + + +ContextTaskMultiplexer.swift - Slather + + + +
Slather logo
+

+Coverage for "ContextTaskMultiplexer.swift" : 81.25% +

+

(13 of 16 relevant lines covered)

+

RouteComposer/Classes/Router/Multiplexers/ContextTaskMultiplexer.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  ContextTaskMultiplexer.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 27/02/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
struct ContextTaskMultiplexer: AnyContextTask, CustomStringConvertible {
12
13
    private var tasks: [AnyContextTask]
14
15
    init(_ tasks: [AnyContextTask]) {
16x
16
        self.tasks = tasks
16x
17
    }
16x
18
19
    mutating func prepare(with context: Any?) throws {
16x
20
        tasks = try tasks.map({
31x
21
            var contextTask = $0
31x
22
            try contextTask.prepare(with: context)
31x
23
            return contextTask
31x
24
        })
31x
25
    }
16x
26
27
    func apply(on viewController: UIViewController, with context: Any?) throws {
17x
28
        try tasks.forEach({ try $0.apply(on: viewController, with: context) })
32x
29
    }
17x
30
31
    var description: String {
!
32
        return String(describing: tasks)
!
33
    }
!
34
35
}
+
+ + + diff --git a/docs/tests/CustomWindowProvider.swift.html b/docs/tests/CustomWindowProvider.swift.html new file mode 100644 index 000000000..02f27ad1b --- /dev/null +++ b/docs/tests/CustomWindowProvider.swift.html @@ -0,0 +1,117 @@ + + + +CustomWindowProvider.swift - Slather + + + +
Slather logo
+

+Coverage for "CustomWindowProvider.swift" : 0.00% +

+

(0 of 3 relevant lines covered)

+

RouteComposer/Classes/Finders/Stack Iterator/CustomWindowProvider.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-11-23.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Returns custom `UIWindow`
9
public struct CustomWindowProvider: WindowProvider {
10
11
    /// Returns key `UIWindow`
12
    public weak var window: UIWindow?
13
14
    /// Constructor
15
    public init(window: UIWindow) {
!
16
        self.window = window
!
17
    }
!
18
19
}
+
+ + + diff --git a/docs/tests/DefaultLogger.swift.html b/docs/tests/DefaultLogger.swift.html new file mode 100644 index 000000000..097ce96f0 --- /dev/null +++ b/docs/tests/DefaultLogger.swift.html @@ -0,0 +1,367 @@ + + + +DefaultLogger.swift - Slather + + + +
Slather logo
+

+Coverage for "DefaultLogger.swift" : 50.00% +

+

(19 of 38 relevant lines covered)

+

RouteComposer/Classes/Logger/DefaultLogger.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  DefaultLogger.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 08/02/2018.
6
//
7
8
import Foundation
9
import os.log
10
11
/// Default Logger implementation
12
public struct DefaultLogger: Logger {
13
14
    /// Log level
15
    public let logLevel: LogLevel
16
17
    private let osLog: OSLog?
18
19
    /// Constructor
20
    ///
21
    /// - Parameter logLevel: DefaultLoggerLevel. Defaulted to warnings.
22
    public init(_ logLevel: LogLevel = .warnings) {
!
23
        self.logLevel = logLevel
!
24
        if #available(iOS 10.0, *) {
!
25
            self.osLog = OSLog.default
!
26
        } else {
!
27
            self.osLog = nil
!
28
        }
!
29
    }
!
30
31
    /// Constructor is available in iOS 10 and later.
32
    ///
33
    /// - Parameters:
34
    ///   - logLevel: DefaultLoggerLevel. Defaulted to warnings.
35
    ///   - osLog: OSLog instance of the app.
36
    @available(iOS 10, *)
37
    public init(_ logLevel: LogLevel = .warnings, osLog: OSLog = OSLog.default) {
9x
38
        self.logLevel = logLevel
9x
39
        self.osLog = osLog
9x
40
    }
9x
41
42
    public func log(_ message: LogMessage) {
665x
43
        switch message {
665x
44
        case .warning(let message):
665x
45
            if logLevel == .verbose || logLevel == .warnings {
!
46
                if #available(iOS 10, *) {
!
47
                    os_log("%@", log: self.osLog ?? OSLog.default, type: .error, message)
!
48
                } else {
!
49
                    NSLog("WARNING: \(message)")
!
50
                }
!
51
            }
665x
52
        case .info(let message):
665x
53
            if logLevel == .verbose {
665x
54
                if #available(iOS 10, *) {
665x
55
                    os_log("%@", log: self.osLog ?? OSLog.default, type: .info, message)
665x
56
                } else {
665x
57
                    NSLog("INFO: \(message)")
!
58
                }
665x
59
            }
665x
60
        case .error(let message):
665x
61
            if #available(iOS 10, *) {
!
62
                os_log("%@", log: self.osLog ?? OSLog.default, type: .fault, message)
!
63
            } else {
!
64
                NSLog("ERROR: \(message)")
!
65
            }
665x
66
        }
665x
67
    }
665x
68
69
}
+
+ + + diff --git a/docs/tests/DefaultRouter+Extension.swift.html b/docs/tests/DefaultRouter+Extension.swift.html new file mode 100644 index 000000000..df8288cbb --- /dev/null +++ b/docs/tests/DefaultRouter+Extension.swift.html @@ -0,0 +1,1537 @@ + + + +DefaultRouter+Extension.swift - Slather + + + +
Slather logo
+

+Coverage for "DefaultRouter+Extension.swift" : 94.89% +

+

(167 of 176 relevant lines covered)

+

RouteComposer/Classes/Router/Internal/DefaultRouter+Extension.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 04/09/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
extension DefaultRouter {
9
10
    struct InterceptorRunner {
11
12
        private var interceptors: [AnyRoutingInterceptor]
13
14
        let context: Any?
15
16
        init(interceptors: [AnyRoutingInterceptor], context: Any?) throws {
92x
17
            self.context = context
92x
18
            self.interceptors = try interceptors.map({
92x
19
                var interceptor = $0
84x
20
                try interceptor.prepare(with: context)
84x
21
                return interceptor
84x
22
            })
84x
23
        }
92x
24
25
        mutating func add(_ interceptor: AnyRoutingInterceptor) throws {
21x
26
            var interceptor = interceptor
21x
27
            try interceptor.prepare(with: context)
21x
28
            interceptors.append(interceptor)
21x
29
        }
21x
30
31
        func run(completion: @escaping (_: InterceptorResult) -> Void) {
87x
32
            guard !interceptors.isEmpty else {
87x
33
                completion(.continueRouting)
6x
34
                return
6x
35
            }
81x
36
            let interceptorToRun = interceptors.count == 1 ? interceptors[0] : InterceptorMultiplexer(interceptors)
81x
37
            interceptorToRun.execute(with: context, completion: completion)
81x
38
        }
81x
39
40
    }
41
42
    struct ContextTaskRunner {
43
44
        var contextTasks: [AnyContextTask]
45
46
        let context: Any?
47
48
        init(contextTasks: [AnyContextTask], context: Any?) throws {
92x
49
            self.context = context
92x
50
            self.contextTasks = try contextTasks.map({
92x
51
                var contextTask = $0
1x
52
                try contextTask.prepare(with: context)
1x
53
                return contextTask
1x
54
            })
1x
55
        }
92x
56
57
        mutating func add(_ contextTask: AnyContextTask) throws {
82x
58
            var contextTask = contextTask
82x
59
            try contextTask.prepare(with: context)
82x
60
            contextTasks.append(contextTask)
82x
61
        }
82x
62
63
        func run(on viewController: UIViewController) throws {
194x
64
            try contextTasks.forEach({
194x
65
                try $0.apply(on: viewController, with: context)
80x
66
            })
80x
67
        }
194x
68
69
    }
70
71
    struct PostTaskRunner {
72
73
        var postTasks: [AnyPostRoutingTask]
74
75
        let context: Any?
76
77
        let delayedRunner: PostTaskDelayedRunner
78
79
        init(postTasks: [AnyPostRoutingTask], context: Any?, delayedRunner: PostTaskDelayedRunner) {
92x
80
            self.context = context
92x
81
            self.postTasks = postTasks
92x
82
            self.delayedRunner = delayedRunner
92x
83
        }
92x
84
85
        mutating func add(_ postTask: AnyPostRoutingTask) throws {
8x
86
            postTasks.append(postTask)
8x
87
        }
8x
88
89
        func run(on viewController: UIViewController) throws {
194x
90
            delayedRunner.add(postTasks: postTasks, to: viewController)
194x
91
        }
194x
92
93
        func commit() throws {
84x
94
            try delayedRunner.run(with: context)
84x
95
        }
84x
96
97
    }
98
99
    struct StepTaskTaskRunner {
100
101
        private let contextTaskRunner: ContextTaskRunner
102
103
        private let postTaskRunner: PostTaskRunner
104
105
        init(contextTaskRunner: ContextTaskRunner, postTaskRunner: PostTaskRunner) {
201x
106
            self.contextTaskRunner = contextTaskRunner
201x
107
            self.postTaskRunner = postTaskRunner
201x
108
        }
201x
109
110
        func run(on viewController: UIViewController) throws {
194x
111
            try contextTaskRunner.run(on: viewController)
194x
112
            try postTaskRunner.run(on: viewController)
194x
113
        }
194x
114
115
    }
116
117
    final class PostTaskDelayedRunner {
118
119
        private struct PostTaskSlip {
120
            // This reference is weak because even though this view controller was created by a fabric but then some other
121
            // view controller in the chain can have an action that will actually remove this view controller from the
122
            // stack. We do not want to keep a strong reference to it and prevent it from deallocation. Potentially it's
123
            // a very rare issue but must be kept in mind.
124
            weak var viewController: UIViewController?
125
126
            let postTask: AnyPostRoutingTask
127
        }
128
129
        // this class is just a placeholder. Router needs at least one post routing task per view controller to
130
        // store a reference there.
131
        private struct EmptyPostTask: AnyPostRoutingTask {
132
133
            func execute(on viewController: UIViewController, with context: Any?, routingStack: [UIViewController]) {
176x
134
            }
176x
135
136
        }
137
138
        private var taskSlips: [PostTaskSlip] = []
139
140
        func add(postTasks: [AnyPostRoutingTask], to viewController: UIViewController) {
194x
141
            guard !postTasks.isEmpty else {
194x
142
                let postTaskSlip = PostTaskSlip(viewController: viewController, postTask: EmptyPostTask())
184x
143
                taskSlips.append(postTaskSlip)
184x
144
                return
184x
145
            }
184x
146
10x
147
            postTasks.forEach({
11x
148
                let postTaskSlip = PostTaskSlip(viewController: viewController, postTask: $0)
11x
149
                taskSlips.append(postTaskSlip)
11x
150
            })
11x
151
        }
10x
152
153
        func run(with context: Any?) throws {
84x
154
            var viewControllers: [UIViewController] = []
84x
155
            taskSlips.forEach({
187x
156
                guard let viewController = $0.viewController, !viewControllers.contains(viewController) else {
187x
157
                    return
1x
158
                }
186x
159
                viewControllers.append(viewController)
186x
160
            })
186x
161
84x
162
            try taskSlips.forEach({ slip in
187x
163
                guard let viewController = slip.viewController else {
187x
164
                    return
!
165
                }
187x
166
                try slip.postTask.execute(on: viewController, with: context, routingStack: viewControllers)
187x
167
            })
187x
168
        }
84x
169
    }
170
171
    class GlobalTaskRunner {
172
173
        private var interceptorRunner: InterceptorRunner
174
175
        private let contextTaskRunner: ContextTaskRunner
176
177
        private let postTaskRunner: PostTaskRunner
178
179
        init(interceptorRunner: InterceptorRunner, contextTaskRunner: ContextTaskRunner, postTaskRunner: PostTaskRunner) {
92x
180
            self.interceptorRunner = interceptorRunner
92x
181
            self.contextTaskRunner = contextTaskRunner
92x
182
            self.postTaskRunner = postTaskRunner
92x
183
        }
92x
184
185
        func taskRunnerFor(step: PerformableStep?) throws -> StepTaskTaskRunner {
202x
186
            guard let interceptableStep = step as? InterceptableStep else {
202x
187
                return StepTaskTaskRunner(contextTaskRunner: self.contextTaskRunner, postTaskRunner: self.postTaskRunner)
48x
188
            }
154x
189
            var contextTaskRunner = self.contextTaskRunner
154x
190
            var postTaskRunner = self.postTaskRunner
154x
191
            if let interceptor = interceptableStep.interceptor {
154x
192
                try interceptorRunner.add(interceptor)
21x
193
            }
154x
194
            if let contextTask = interceptableStep.contextTask {
154x
195
                try contextTaskRunner.add(contextTask)
82x
196
            }
154x
197
            if let postTask = interceptableStep.postTask {
154x
198
                try postTaskRunner.add(postTask)
8x
199
            }
154x
200
            return StepTaskTaskRunner(contextTaskRunner: contextTaskRunner, postTaskRunner: postTaskRunner)
154x
201
        }
154x
202
203
        func executeInterceptors(completion: @escaping (_: InterceptorResult) -> Void) {
87x
204
            interceptorRunner.run(completion: completion)
87x
205
        }
87x
206
207
        func runPostTasks() throws {
84x
208
            try postTaskRunner.commit()
84x
209
        }
84x
210
211
    }
212
213
    /// Each post action needs to know a view controller is should be applied to.
214
    /// This decorator adds functionality of storing `UIViewController`s created by the `Factory` and frees
215
    /// custom factories implementations from dealing with it. Mostly it is important for ContainerFactories
216
    /// which create merged view controllers without `Router`'s help.
217
    struct FactoryDecorator: AnyFactory, CustomStringConvertible {
218
219
        private var factory: AnyFactory
220
221
        private let stepTaskRunner: StepTaskTaskRunner
222
223
        let action: AnyAction
224
225
        init(factory: AnyFactory, viewControllerTaskRunner: StepTaskTaskRunner) {
110x
226
            self.factory = factory
110x
227
            self.action = factory.action
110x
228
            self.stepTaskRunner = viewControllerTaskRunner
110x
229
        }
110x
230
231
        mutating func prepare(with context: Any?) throws {
110x
232
            return try factory.prepare(with: context)
110x
233
        }
110x
234
235
        func build(with context: Any?) throws -> UIViewController {
104x
236
            let viewController = try factory.build(with: context)
104x
237
            try stepTaskRunner.run(on: viewController)
104x
238
            return viewController
104x
239
        }
104x
240
241
        mutating func scrapeChildren(from factories: [AnyFactory]) throws -> [AnyFactory] {
110x
242
            return try factory.scrapeChildren(from: factories)
110x
243
        }
110x
244
245
        var description: String {
69x
246
            return String(describing: factory)
69x
247
        }
69x
248
249
    }
250
251
    final class DefaultDelayedIntegrationHandler: DelayedActionIntegrationHandler {
252
253
        var containerViewController: ContainerViewController?
254
255
        var delayedViewControllers: [UIViewController] = []
256
257
        let logger: Logger?
258
259
        init(logger: Logger?) {
88x
260
            self.logger = logger
88x
261
        }
88x
262
263
        func update(containerViewController: ContainerViewController, animated: Bool, completion: @escaping () -> Void) {
2x
264
            guard self.containerViewController == nil else {
2x
265
                purge(animated: animated, completion: {
!
266
                    self.update(containerViewController: containerViewController, animated: animated, completion: completion)
!
267
                })
!
268
                return
!
269
            }
2x
270
            self.containerViewController = containerViewController
2x
271
            self.delayedViewControllers = containerViewController.containedViewControllers
2x
272
            logger?.log(.info("Container \(String(describing: containerViewController)) will be used for the delayed integration."))
2x
273
            completion()
2x
274
        }
2x
275
276
        func update(delayedViewControllers: [UIViewController]) {
3x
277
            self.delayedViewControllers = delayedViewControllers
3x
278
        }
3x
279
280
        func purge(animated: Bool, completion: @escaping  () -> Void) {
159x
281
            guard let containerViewController = containerViewController else {
159x
282
                completion()
157x
283
                return
157x
284
            }
157x
285
2x
286
            guard !delayedViewControllers.isEqual(to: containerViewController.containedViewControllers) else {
2x
287
                self.containerViewController = nil
!
288
                self.delayedViewControllers = []
!
289
                completion()
!
290
                return
!
291
            }
2x
292
2x
293
            containerViewController.replace(containedViewControllers: delayedViewControllers, animated: animated, completion: {
2x
294
                self.logger?.log(.info("View controllers \(String(describing: self.delayedViewControllers)) were integrated together into \(containerViewController)"))
2x
295
                self.containerViewController = nil
2x
296
                self.delayedViewControllers = []
2x
297
                completion()
2x
298
            })
2x
299
        }
2x
300
301
    }
302
303
}
+
+ + + diff --git a/docs/tests/DefaultRouter.swift.html b/docs/tests/DefaultRouter.swift.html new file mode 100644 index 000000000..55b119430 --- /dev/null +++ b/docs/tests/DefaultRouter.swift.html @@ -0,0 +1,1297 @@ + + + +DefaultRouter.swift - Slather + + + +
Slather logo
+

+Coverage for "DefaultRouter.swift" : 95.69% +

+

(200 of 209 relevant lines covered)

+

RouteComposer/Classes/Router/DefaultRouter.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// Default `Router` implementation
9
public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
10
11
    /// A `Logger` instance to be used by `DefaultRouter`.
12
    public let logger: Logger?
13
14
    private var interceptors: [AnyRoutingInterceptor] = []
15
16
    private var contextTasks: [AnyContextTask] = []
17
18
    private var postTasks: [AnyPostRoutingTask] = []
19
20
    /// Constructor
21
    ///
22
    /// - Parameter logger: A `Logger` instance to be used by the `DefaultRouter`.
23
    public init(logger: Logger? = nil) {
22x
24
        self.logger = logger
22x
25
    }
22x
26
27
    public mutating func add<RI: RoutingInterceptor>(_ interceptor: RI) where RI.Context == Any? {
10x
28
        self.interceptors.append(RoutingInterceptorBox(interceptor))
10x
29
    }
10x
30
31
    public mutating func add<CT: ContextTask>(_ contextTask: CT) where CT.Context == Any? {
1x
32
        self.contextTasks.append(ContextTaskBox(contextTask))
1x
33
    }
1x
34
35
    public mutating func add<PT: PostRoutingTask>(_ postTask: PT) where PT.Context == Any? {
1x
36
        self.postTasks.append(PostRoutingTaskBox(postTask))
1x
37
    }
1x
38
39
    public func navigate<ViewController: UIViewController, Context>(to step: DestinationStep<ViewController, Context>,
40
                                                                    with context: Context,
41
                                                                    animated: Bool = true,
42
                                                                    completion: ((_: RoutingResult) -> Void)? = nil) throws {
92x
43
        assertIfNotMainThread(logger: logger)
92x
44
92x
45
        let taskStack = try prepareTaskStack(with: context)
92x
46
92x
47
        // Builds stack of factories and finds a view controller to start a navigation process from.
92x
48
        // Returns (rootViewController, factories) tuple
92x
49
        // where rootViewController is the origin of the chain of views to be built for a given destination.
92x
50
        let navigationStack = try prepareFactoriesStack(to: step, with: context, taskStack: taskStack)
92x
51
92x
52
        let viewController = navigationStack.rootViewController,
92x
53
                factoriesStack = navigationStack.factories
92x
54
92x
55
        // Checks if the view controllers that are currently presented from the origin view controller, can be dismissed.
92x
56
        if let viewController = Array([[viewController.allParents.last ?? viewController], viewController.allPresentedViewControllers].joined()).nonDismissibleViewController {
92x
57
            throw RoutingError.generic(.init("\(String(describing: viewController)) view controller cannot " +
4x
58
                    "be dismissed."))
4x
59
        }
88x
60
88x
61
        // Executes interceptors associated to each view in the chain. All the interceptors must succeed to
88x
62
        // continue navigation process. This operation is async.
88x
63
        taskStack.executeInterceptors { [weak viewController] result in
88x
64
            self.assertIfNotMainThread(logger: self.logger)
87x
65
87x
66
            if case let .failure(error) = result {
87x
67
                completion?(.failure(error))
1x
68
                return
1x
69
            }
86x
70
86x
71
            guard let viewController = viewController else {
86x
72
                completion?(.failure(RoutingError.generic(.init("A view controller that has been chosen as a " +
!
73
                        "starting point of the navigation process was destroyed while the router was waiting for the interceptors to finish."))))
!
74
                return
!
75
            }
86x
76
86x
77
            // Closes all the presented view controllers above the found view controller to be able
86x
78
            // to build a new stack if needed.
86x
79
            // This operation is async.
86x
80
            // It was already confirmed that they can be dismissed.
86x
81
            self.dismissPresentedIfNeeded(from: viewController, animated: animated) {
86x
82
                // Builds view controller's stack using factories.
86x
83
                // This operation is async.
86x
84
                self.buildViewControllerStack(starting: viewController,
86x
85
                        with: context,
86x
86
                        using: factoriesStack,
86x
87
                        animated: animated) { viewController, result in
86x
88
                    self.makeVisibleInParentContainer(viewController, animated: animated)
86x
89
                    do {
86x
90
                        if case let .failure(error) = result {
86x
91
                            throw error
2x
92
                        }
84x
93
                        try taskStack.runPostTasks()
84x
94
                        self.logger?.log(.info("Successfully finished the navigation process."))
84x
95
                        completion?(result)
84x
96
                    } catch let error {
84x
97
                        self.logger?.log(.info("Unsuccessfully finished the navigation process."))
2x
98
                        completion?(.failure(error))
2x
99
                    }
86x
100
                }
86x
101
            }
86x
102
        }
86x
103
    }
88x
104
105
    private func prepareTaskStack(with context: Any?) throws -> GlobalTaskRunner {
92x
106
        let interceptorRunner = try InterceptorRunner(interceptors: self.interceptors, context: context)
92x
107
        let contextTaskRunner = try ContextTaskRunner(contextTasks: self.contextTasks, context: context)
92x
108
        let postTaskDelayedRunner = PostTaskDelayedRunner()
92x
109
        let postTaskRunner = PostTaskRunner(postTasks: self.postTasks, context: context, delayedRunner: postTaskDelayedRunner)
92x
110
        return GlobalTaskRunner(interceptorRunner: interceptorRunner, contextTaskRunner: contextTaskRunner, postTaskRunner: postTaskRunner)
92x
111
    }
92x
112
113
    private func prepareFactoriesStack(to finalStep: RoutingStep, with context: Any?, taskStack: GlobalTaskRunner) throws -> (rootViewController: UIViewController,
114
                                                                                                                              factories: [AnyFactory]) {
92x
115
        logger?.log(.info("Started to search for the view controller to start the navigation process from."))
92x
116
92x
117
        let result = try sequence(first: finalStep, next: { ($0 as? ChainableStep)?.getPreviousStep(with: context) })
546x
118
                .compactMap({ $0 as? PerformableStep })
546x
119
                .reduce((rootViewController: UIViewController?, factories: [AnyFactory])(rootViewController: nil, factories: []), { (result, step) in
286x
120
                    guard result.rootViewController == nil else {
286x
121
                        return result
84x
122
                    }
202x
123
202x
124
                    // Creates a class responsible to run the tasks for this particular step
202x
125
                    let viewControllerTaskRunner = try taskStack.taskRunnerFor(step: step)
202x
126
202x
127
                    // Performs current step
202x
128
                    switch try step.perform(with: context) {
202x
129
                    case .success(let viewController):
202x
130
                        logger?.log(.info("\(String(describing: step)) found " +
91x
131
                                "\(String(describing: viewController)) to start the navigation process from."))
91x
132
                        try viewControllerTaskRunner.run(on: viewController)
91x
133
                        return (rootViewController: viewController, result.factories)
91x
134
                    case .build(let originalFactory):
202x
135
                        // If the view controller to start from is not found, but the current step has a `Factory` to build it,
110x
136
                        // then add factory to the stack
110x
137
                        logger?.log(.info("\(String(describing: step)) hasn't found a corresponding view " +
110x
138
                                "controller in the stack, so it will be built using \(String(describing: originalFactory))."))
110x
139
110x
140
                        // Wrap the `Factory` with the decorator that will
110x
141
                        // handle the view controller and post task chain after the view controller creation.
110x
142
                        var factory = FactoryDecorator(factory: originalFactory,
110x
143
                                viewControllerTaskRunner: viewControllerTaskRunner)
110x
144
110x
145
                        // Prepares the `Factory` for integration
110x
146
                        // If a `Factory` cannot prepare itself (e.g. does not have enough data in context)
110x
147
                        // then the view controllers stack can not be built
110x
148
                        try factory.prepare(with: context)
110x
149
110x
150
                        // Allows to the `Factory` to change the current factory stack if needed.
110x
151
                        var factories = try factory.scrapeChildren(from: result.factories)
110x
152
110x
153
                        // Adds the `Factory` to the beginning of the stack as the router is reading the configuration backwards.
110x
154
                        factories.insert(factory, at: 0)
110x
155
                        return (rootViewController: result.rootViewController, factories: factories)
110x
156
                    case .none:
202x
157
                        logger?.log(.info("\(String(describing: step)) hasn't found a corresponding view " +
!
158
                                "controller in the stack, so router will continue to search."))
!
159
                        return result
!
160
                    }
202x
161
                })
201x
162
92x
163
        //Throws an exception if it hasn't found a view controller to start the stack from.
92x
164
        guard let rootViewController = result.rootViewController else {
92x
165
            throw RoutingError.generic(.init("Unable to start the navigation process as the view controller to start from was not found."))
!
166
        }
92x
167
92x
168
        return (rootViewController: rootViewController, factories: result.factories)
92x
169
    }
92x
170
171
    // Loops through the list of factories and builds their view controllers in sequence.
172
    // Some actions can be asynchronous, like push, modal or presentations,
173
    // so it performs them asynchronously
174
    private func buildViewControllerStack(starting rootViewController: UIViewController,
175
                                          with context: Any?,
176
                                          using factories: [AnyFactory],
177
                                          animated: Bool,
178
                                          completion: @escaping ((_: UIViewController, _: RoutingResult) -> Void)) {
86x
179
        var factories = factories
86x
180
86x
181
        let delayedIntegrationHandler = DefaultDelayedIntegrationHandler(logger: logger)
86x
182
86x
183
        func buildViewController(from previousViewController: UIViewController) {
159x
184
            guard !factories.isEmpty else {
159x
185
                delayedIntegrationHandler.purge(animated: animated, completion: {
84x
186
                    return completion(previousViewController, .success)
84x
187
                })
84x
188
                return
84x
189
            }
84x
190
            let factory = factories.removeFirst()
75x
191
            // If the previous view controller is created/found but it's view is not loaded or it has no window,
75x
192
            // it was cached by the container view controller like it would be in a `UITabBarController`s
75x
193
            // tab that was never activated. So the router will have to activate it first.
75x
194
            // Example: `UITabBarController` contains a navigation controller in the tab that was never opened and the router is going
75x
195
            // to push a view controller into. UINavigationController in this case will not be able to update its content properly.
75x
196
            if !previousViewController.isViewLoaded || previousViewController.view.window == nil {
75x
197
                makeVisibleInParentContainer(previousViewController, animated: false)
15x
198
            }
75x
199
75x
200
            do {
75x
201
                let newViewController = try factory.build(with: context)
75x
202
                logger?.log(.info("\(String(describing: factory)) built a " +
75x
203
                        "\(String(describing: newViewController))."))
75x
204
                let nextAction = factories.first?.action
75x
205
                factory.action.perform(with: newViewController, on: previousViewController, with: delayedIntegrationHandler, nextAction: nextAction, animated: animated) { result in
75x
206
                    self.assertIfNotMainThread(logger: self.logger)
74x
207
                    if case let .failure(error) = result {
74x
208
                        self.logger?.log(.error("\(String(describing: factory.action)) has stopped the navigation process " +
1x
209
                                "as it was not able to build a view controller into a stack."))
1x
210
                        completion(newViewController, .failure(error))
1x
211
                        return
1x
212
                    }
73x
213
                    self.logger?.log(.info("\(String(describing: factory.action)) has applied to " +
73x
214
                            "\(String(describing: previousViewController)) with \(String(describing: newViewController))."))
73x
215
                    buildViewController(from: newViewController)
73x
216
                }
73x
217
            } catch let error {
75x
218
                completion(previousViewController, .failure(error))
1x
219
            }
75x
220
        }
75x
221
86x
222
        logger?.log(.info(factories.isEmpty ? "No view controllers needed to be integrated into the stack." : "Started to build the view controllers stack."))
86x
223
        buildViewController(from: rootViewController)
86x
224
    }
86x
225
226
    // Activates the origin view controller of viewController
227
    private func makeVisibleInParentContainer(_ viewController: UIViewController, animated: Bool) {
101x
228
        var currentViewController = viewController
101x
229
        viewController.allParents.forEach({
101x
230
            if let container = $0 as? ContainerViewController {
90x
231
                container.makeVisible(currentViewController, animated: animated)
90x
232
                logger?.log(.info("Made \(String(describing: currentViewController)) visible in \(String(describing: container))"))
90x
233
            }
90x
234
            currentViewController = $0
90x
235
        })
90x
236
    }
101x
237
238
    // Dismisses all the view controllers presented if there are any
239
    private func dismissPresentedIfNeeded(from viewController: UIViewController, animated: Bool, completion: @escaping (() -> Void)) {
86x
240
        if let presentedController = viewController.presentedViewController {
86x
241
            if !presentedController.isBeingDismissed {
8x
242
                viewController.dismiss(animated: animated) {
8x
243
                    self.logger?.log(.info("Dismissed all the view controllers presented from \(String(describing: viewController))"))
8x
244
                    completion()
8x
245
                }
8x
246
            } else {
8x
247
                self.logger?.log(.info("Trying to dismiss \(String(describing: presentedController)) while it is being dismissed"))
!
248
                completion()
!
249
            }
8x
250
        } else {
86x
251
            completion()
78x
252
        }
86x
253
    }
86x
254
255
}
+
+ + + diff --git a/docs/tests/DefaultStackIterator.swift.html b/docs/tests/DefaultStackIterator.swift.html new file mode 100644 index 000000000..c107f5a03 --- /dev/null +++ b/docs/tests/DefaultStackIterator.swift.html @@ -0,0 +1,332 @@ + + + +DefaultStackIterator.swift - Slather + + + +
Slather logo
+

+Coverage for "DefaultStackIterator.swift" : 100.00% +

+

(21 of 21 relevant lines covered)

+

RouteComposer/Classes/Finders/Stack Iterator/DefaultStackIterator.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-11-07.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Default implementation of `StackIterator` protocol
9
public struct DefaultStackIterator: StackIterator {
10
11
    /// A starting point in the `UIViewController`s stack
12
    ///
13
    /// - topMost: Start from the topmost `UIViewController`
14
    /// - root: Start from the `UIWindow`s root `UIViewController`
15
    public enum StartingPoint {
16
17
        /// Start from the topmost `UIViewController`
18
        case topmost
19
20
        /// Start from the `UIWindow`s root `UIViewController`
21
        case root
22
23
    }
24
25
    /// `SearchOptions` to be used by `StackIteratingFinder`
26
    public let options: SearchOptions
27
28
    /// A starting point in the `UIViewController`s stack
29
    public let startingPoint: StartingPoint
30
31
    /// `WindowProvider` to get proper `UIWindow`
32
    public let windowProvider: WindowProvider
33
34
    var startingViewController: UIViewController? {
151x
35
        switch startingPoint {
151x
36
        case .topmost:
151x
37
            return windowProvider.window?.topmostViewController
134x
38
        case .root:
151x
39
            return windowProvider.window?.rootViewController
17x
40
        }
151x
41
    }
151x
42
43
    /// Constructor
44
    public init(options: SearchOptions = .fullStack, startingPoint: StartingPoint = .topmost, windowProvider: WindowProvider = KeyWindowProvider()) {
157x
45
        self.startingPoint = startingPoint
157x
46
        self.options = options
157x
47
        self.windowProvider = windowProvider
157x
48
    }
157x
49
50
    /// Returns `UIViewController` instance if found
51
    ///
52
    /// - Parameter predicate: A block that contains `UIViewController` matching condition
53
    public func firstViewController(where predicate: (UIViewController) -> Bool) -> UIViewController? {
149x
54
        guard let rootViewController = startingViewController,
149x
55
              let viewController = UIViewController.findViewController(in: rootViewController, options: options, using: predicate) else {
149x
56
            return nil
83x
57
        }
83x
58
66x
59
        return viewController
66x
60
    }
149x
61
62
}
+
+ + + diff --git a/docs/tests/DelayedIntegrationFactory.swift.html b/docs/tests/DelayedIntegrationFactory.swift.html new file mode 100644 index 000000000..6b89975ce --- /dev/null +++ b/docs/tests/DelayedIntegrationFactory.swift.html @@ -0,0 +1,247 @@ + + + +DelayedIntegrationFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "DelayedIntegrationFactory.swift" : 100.00% +

+

(23 of 23 relevant lines covered)

+

RouteComposer/Classes/Router/Internal/DelayedIntegrationFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  DelayedIntegrationFactory.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 03/03/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
struct DelayedIntegrationFactory<Context>: CustomStringConvertible {
12
13
    var factory: AnyFactory
14
15
    var contextTasks: [AnyContextTask]
16
17
    init(_ factory: AnyFactory, contextTasks: [AnyContextTask] = []) {
56x
18
        self.factory = factory
56x
19
        self.contextTasks = contextTasks
56x
20
    }
56x
21
22
    mutating func add(_ contextTask: AnyContextTask) {
3x
23
        self.contextTasks.append(contextTask)
3x
24
    }
3x
25
26
    mutating func prepare(with context: Context) throws {
23x
27
        try factory.prepare(with: context)
23x
28
        contextTasks = try contextTasks.map({
23x
29
            var contextTask = $0
3x
30
            try contextTask.prepare(with: context)
3x
31
            return contextTask
3x
32
        })
3x
33
    }
23x
34
35
    func build(with context: Context, in childViewControllers: inout [UIViewController]) throws {
50x
36
        let viewController = try factory.build(with: context)
50x
37
        try contextTasks.forEach({ try $0.apply(on: viewController, with: context)})
50x
38
        try factory.action.perform(embedding: viewController, in: &childViewControllers)
50x
39
    }
50x
40
41
    public var description: String {
1x
42
        return String(describing: factory)
1x
43
    }
1x
44
45
}
+
+ + + diff --git a/docs/tests/DestinationStep.swift.html b/docs/tests/DestinationStep.swift.html new file mode 100644 index 000000000..56cc3a43a --- /dev/null +++ b/docs/tests/DestinationStep.swift.html @@ -0,0 +1,322 @@ + + + +DestinationStep.swift - Slather + + + +
Slather logo
+

+Coverage for "DestinationStep.swift" : 100.00% +

+

(18 of 18 relevant lines covered)

+

RouteComposer/Classes/DestinationStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-09-17.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Represents a single step for the `Router` to make.
9
public struct DestinationStep<VC: UIViewController, C>: RoutingStep, ChainableStep {
10
11
    /// Type of the `ViewController` associated with the step
12
    public typealias ViewController = VC
13
14
    /// Type of the `Context` associated with the step
15
    public typealias Context = C
16
17
    func getPreviousStep(with context: Any?) -> RoutingStep? {
274x
18
        return destinationStep
274x
19
    }
274x
20
21
    let destinationStep: RoutingStep
22
23
    init(_ destinationStep: RoutingStep) {
279x
24
        self.destinationStep = destinationStep
279x
25
    }
279x
26
27
    /// Adapts context and view controller type dependencies.
28
    ///
29
    /// *NB:* Developer guaranties that this types will compliment in runtime.
30
    public func unsafelyRewrapped<VC: UIViewController, C>() -> DestinationStep<VC, C> {
3x
31
        return DestinationStep<VC, C>(destinationStep)
3x
32
    }
3x
33
34
    /// Allows to avoid container view controller check.
35
    ///
36
    /// *NB:* Developer guaranties that it will be there in the runtime.
37
    public func expectingContainer<VC: ContainerViewController>() -> DestinationStep<VC, Context> {
9x
38
        return DestinationStep<VC, Context>(destinationStep)
9x
39
    }
9x
40
41
}
42
43
/// A step that has a context type Optional(Any) can be build with any type of context passed to the router.
44
extension DestinationStep where DestinationStep.Context == Any? {
45
46
    /// Allows to avoid container view controller check. This method is available only for the steps that are
47
    /// able to accept any type of context.
48
    ///
49
    /// *NB:* Developer guaranties that it will be there in the runtime.
50
    public func expectingContainer<VC: ContainerViewController, C>() -> DestinationStep<VC, C> {
12x
51
        return DestinationStep<VC, C>(destinationStep)
12x
52
    }
12x
53
54
    /// Allows to compliment to the type check. A step that has context equal to Optional(Any) can be build
55
    /// with any type of context passed to the router.
56
    public func adaptingContext<C>() -> DestinationStep<ViewController, C> {
7x
57
        return DestinationStep<ViewController, C>(destinationStep)
7x
58
    }
7x
59
60
}
+
+ + + diff --git a/docs/tests/DismissalMethodProvidingContextTask.swift.html b/docs/tests/DismissalMethodProvidingContextTask.swift.html new file mode 100644 index 000000000..ffe305e9a --- /dev/null +++ b/docs/tests/DismissalMethodProvidingContextTask.swift.html @@ -0,0 +1,167 @@ + + + +DismissalMethodProvidingContextTask.swift - Slather + + + +
Slather logo
+

+Coverage for "DismissalMethodProvidingContextTask.swift" : 100.00% +

+

(6 of 6 relevant lines covered)

+

RouteComposer/Classes/Extra/DismissalMethodProvidingContextTask.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-03-19.
3
// Copyright © 2019 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// `DismissalMethodProvidingContextTask` allows to provide the way to dismiss the `UIViewController` using a preset configuration.
10
/// The `UIViewController` should conform to `Dismissible` protocol and call `Dismissible.dismissViewController(...)` method
11
/// when it needs to be dismissed to trigger the dismissal process implemented in `DismissalMethodProvidingContextTask.init(...)`
12
/// constructor.
13
public struct DismissalMethodProvidingContextTask<VC: Dismissible, C>: ContextTask {
14
15
    let dismissalBlock: (_: VC.DismissalTargetContext, _: Bool, _: ((_: RoutingResult) -> Void)?) -> Void
16
17
    /// Constructor
18
    ///
19
    /// - Parameter dismissalBlock: Block that will trigger the dismissal process when `Dismissible` `UIViewController` calls
20
    ///    `Dismissible.dismissViewController(...)` method.
21
    public init(dismissalBlock: @escaping (_: VC.DismissalTargetContext, _: Bool, _: ((_: RoutingResult) -> Void)?) -> Void) {
12x
22
        self.dismissalBlock = dismissalBlock
12x
23
    }
12x
24
25
    public func apply(on viewController: VC, with context: C) throws {
11x
26
        viewController.dismissalBlock = dismissalBlock
11x
27
    }
11x
28
29
}
+
+ + + diff --git a/docs/tests/Dismissible.swift.html b/docs/tests/Dismissible.swift.html new file mode 100644 index 000000000..d7dc30ac8 --- /dev/null +++ b/docs/tests/Dismissible.swift.html @@ -0,0 +1,442 @@ + + + +Dismissible.swift - Slather + + + +
Slather logo
+

+Coverage for "Dismissible.swift" : 66.67% +

+

(14 of 21 relevant lines covered)

+

RouteComposer/Classes/Extra/Dismissible.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-03-19.
3
// Copyright © 2019 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
var associatedObjectHandle: UInt8 = 0
10
11
/// `UIViewController` should conform to `Dismissible` protocol to be used with `DismissalMethodProvidingContextTask`.
12
public protocol Dismissible where Self: UIViewController {
13
14
    /// Type of instance that `Dismissible` `UIViewController` will provide on dismissal.
15
    associatedtype DismissalTargetContext
16
17
    /// Property to store the dismissal block provided by `DismissalMethodProvidingContextTask`
18
    var dismissalBlock: ((_: DismissalTargetContext, _: Bool, _: ((_: RoutingResult) -> Void)?) -> Void)? { get set }
19
20
}
21
22
public extension Dismissible {
23
24
    /// Dismisses current `UIViewController` using dismissal block provided by `DismissalMethodProvidingContextTask`
25
    ///
26
    /// - Parameters:
27
    ///   - context: `DismissalTargetContext` required to be dismissed.
28
    ///   - animated: Dismissal process should be animated if set to `true`
29
    ///   - completion: The completion block.
30
    func dismissViewController(with context: DismissalTargetContext, animated: Bool, completion: ((_: RoutingResult) -> Void)? = nil) {
4x
31
        guard let dismissalBlock = self.dismissalBlock else {
4x
32
            let message = "Dismissal block has not been set."
!
33
            assertionFailure(message)
!
34
            completion?(.failure(RoutingError.compositionFailed(.init(message))))
!
35
            return
!
36
        }
4x
37
        dismissalBlock(context, animated, completion)
4x
38
    }
4x
39
40
}
41
42
public extension Dismissible where DismissalTargetContext == Any? {
43
44
    /// Dismisses current `UIViewController` using dismissal block provided by `DismissalMethodProvidingContextTask`
45
    ///
46
    /// - Parameters:
47
    ///   - animated: Dismissal process should be animated if set to `true`
48
    ///   - completion: The completion block.
49
    func dismissViewController(animated: Bool, completion: ((_: RoutingResult) -> Void)? = nil) {
!
50
        dismissViewController(with: nil, animated: animated, completion: completion)
!
51
    }
!
52
53
}
54
55
public extension Dismissible where DismissalTargetContext == Void {
56
57
    /// Dismisses current `UIViewController` using dismissal block provided by `DismissalMethodProvidingContextTask`
58
    ///
59
    /// - Parameters:
60
    ///   - animated: Dismissal process should be animated if set to `true`
61
    ///   - completion: The completion block.
62
    func dismissViewController(animated: Bool, completion: ((_: RoutingResult) -> Void)? = nil) {
4x
63
        dismissViewController(with: (), animated: animated, completion: completion)
4x
64
    }
4x
65
66
}
67
68
/// `DismissibleWithRuntimeStorage` simplifies `Dismissible` protocol conformance implementing required
69
/// `dismissalBlock` using Objective C runtime.
70
public protocol DismissibleWithRuntimeStorage: Dismissible {
71
}
72
73
public extension DismissibleWithRuntimeStorage {
74
75
    var dismissalBlock: ((_: DismissalTargetContext, _: Bool, _: ((_: RoutingResult) -> Void)?) -> Void)? {
76
        get {
5x
77
            return objc_getAssociatedObject(self, &associatedObjectHandle) as? ((_: DismissalTargetContext, _: Bool, _: ((_: RoutingResult) -> Void)?) -> Void)
5x
78
        }
5x
79
        set {
11x
80
            objc_setAssociatedObject(self, &associatedObjectHandle, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
11x
81
        }
11x
82
    }
83
84
}
+
+ + + diff --git a/docs/tests/Factory.swift.html b/docs/tests/Factory.swift.html new file mode 100644 index 000000000..d11f272ab --- /dev/null +++ b/docs/tests/Factory.swift.html @@ -0,0 +1,392 @@ + + + +Factory.swift - Slather + + + +
Slather logo
+

+Coverage for "Factory.swift" : 65.22% +

+

(15 of 23 relevant lines covered)

+

RouteComposer/Classes/Factory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// The `Factory` protocol should be implemented by the instance that produces any types of the view controllers
9
public protocol Factory: AbstractFactory {
10
11
    /// Type of `UIViewController` that `Factory` can build
12
    associatedtype ViewController
13
14
    /// `Context` to be passed into `UIViewController`
15
    associatedtype Context
16
17
    /// Builds a `UIViewController` that will be integrated into the stack
18
    ///
19
    /// - Parameter context: A `Context` instance that is provided to the `Router`.
20
    /// - Returns: The built `UIViewController` instance.
21
    /// - Throws: The `RoutingError` if build did not succeed.
22
    func build(with context: Context) throws -> ViewController
23
24
}
25
26
/// Default implementation
27
public extension Factory {
28
29
    /// Default implementation does nothing
30
    mutating func prepare(with context: Context) throws {
107x
31
    }
107x
32
33
    /// Prepares the `Factory` and builds a `UIViewController`
34
    func buildPrepared(with context: Context) throws -> ViewController {
1x
35
        var factory = self
1x
36
        try factory.prepare(with: context)
1x
37
        return try factory.build(with: context)
1x
38
    }
1x
39
40
}
41
42
/// Default implementation for any context
43
public extension Factory where Context == Any? {
44
45
    /// Builds a `Factory`'s view controller.
46
    func build() throws -> ViewController {
6x
47
        return try build(with: nil)
6x
48
    }
6x
49
50
    /// Prepares the `Factory` and builds a `UIViewController`
51
    func buildPrepared() throws -> ViewController {
2x
52
        var factory = self
2x
53
        try factory.prepare()
2x
54
        return try factory.build()
2x
55
    }
2x
56
57
}
58
59
/// Default implementation for an empty context
60
public extension Factory where Context == Void {
61
62
    /// Builds a `Factory`'s view controller.
63
    func build() throws -> ViewController {
!
64
        return try build(with: ())
!
65
    }
!
66
67
    /// Prepares the `Factory` and builds a `UIViewController`
68
    func buildPrepared() throws -> ViewController {
!
69
        var factory = self
!
70
        try factory.prepare()
!
71
        return try factory.build()
!
72
    }
!
73
74
}
+
+ + + diff --git a/docs/tests/FactoryBox.swift.html b/docs/tests/FactoryBox.swift.html new file mode 100644 index 000000000..0e18e0793 --- /dev/null +++ b/docs/tests/FactoryBox.swift.html @@ -0,0 +1,197 @@ + + + +FactoryBox.swift - Slather + + + +
Slather logo
+

+Coverage for "FactoryBox.swift" : 87.50% +

+

(14 of 16 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/FactoryBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
struct FactoryBox<F: Factory>: PreparableAnyFactory, AnyFactoryBox, MainThreadChecking, CustomStringConvertible {
8
9
    typealias FactoryType = F
10
11
    var factory: F
12
13
    let action: AnyAction
14
15
    var isPrepared = false
16
17
    init?(_ factory: F, action: AnyAction) {
257x
18
        guard !(factory is NilEntity) else {
257x
19
            return nil
62x
20
        }
195x
21
        self.factory = factory
195x
22
        self.action = action
195x
23
    }
195x
24
25
    func build(with context: Any?) throws -> UIViewController {
101x
26
        guard let typedContext = Any?.some(context as Any) as? FactoryType.Context else {
101x
27
            throw RoutingError.typeMismatch(FactoryType.Context.self, .init("\(String(describing: factory.self)) does " +
!
28
                    "not accept \(String(describing: context.self)) as a context."))
!
29
        }
101x
30
        assertIfNotMainThread()
101x
31
        assertIfNotPrepared()
101x
32
        return try factory.build(with: typedContext)
101x
33
    }
101x
34
35
}
+
+ + + diff --git a/docs/tests/Finder.swift.html b/docs/tests/Finder.swift.html new file mode 100644 index 000000000..8637cb1e8 --- /dev/null +++ b/docs/tests/Finder.swift.html @@ -0,0 +1,257 @@ + + + +Finder.swift - Slather + + + +
Slather logo
+

+Coverage for "Finder.swift" : 0.00% +

+

(0 of 6 relevant lines covered)

+

RouteComposer/Classes/Finder.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// An instance that conforms to the `Finder` protocol will be used by the `Router` to find out if some `UIViewController`
10
/// instance is integrated into the view controller stack
11
public protocol Finder {
12
13
    /// Type of `UIViewController` that `Finder` can find
14
    associatedtype ViewController: UIViewController
15
16
    /// Type of `Context` object that `Finder` can deal with
17
    associatedtype Context
18
19
    /// Returns the view controller instance if it is present in the stack.
20
    ///
21
    /// - Parameter context: The `Context` instance passed to the `Router`.
22
    /// - Returns: The `UIViewController` instance that the `Router` is looking for, nil otherwise.
23
    func findViewController(with context: Context) -> ViewController?
24
25
}
26
27
public extension Finder where Context == Any? {
28
29
    /// Returns the view controller instance if it is present in the stack.
30
    ///
31
    /// - Returns: The `UIViewController` instance that the `Router` is looking for, nil otherwise.
32
    func findViewController() -> ViewController? {
!
33
        return findViewController(with: nil)
!
34
    }
!
35
36
}
37
38
public extension Finder where Context == Void {
39
40
    /// Returns the view controller instance if it is present in the stack.
41
    ///
42
    /// - Returns: The `UIViewController` instance that the `Router` is looking for, nil otherwise.
43
    func findViewController() -> ViewController? {
!
44
        return findViewController(with: ())
!
45
    }
!
46
47
}
+
+ + + diff --git a/docs/tests/FinderBox.swift.html b/docs/tests/FinderBox.swift.html new file mode 100644 index 000000000..cb0c025c8 --- /dev/null +++ b/docs/tests/FinderBox.swift.html @@ -0,0 +1,172 @@ + + + +FinderBox.swift - Slather + + + +
Slather logo
+

+Coverage for "FinderBox.swift" : 100.00% +

+

(16 of 16 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/FinderBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
struct FinderBox<F: Finder>: AnyFinder, CustomStringConvertible {
8
9
    let finder: F
10
11
    init?(_ finder: F) {
218x
12
        guard !(finder is NilEntity) else {
218x
13
            return nil
43x
14
        }
175x
15
        self.finder = finder
175x
16
    }
175x
17
18
    func findViewController(with context: Any?) throws -> UIViewController? {
159x
19
        guard let typedContext = Any?.some(context as Any) as? F.Context else {
159x
20
            throw RoutingError.typeMismatch(F.Context.self, .init("\(String(describing: F.self)) does " +
4x
21
                    "not accept \(String(describing: context.self)) as a context."))
4x
22
        }
155x
23
        return finder.findViewController(with: typedContext)
155x
24
    }
159x
25
26
    var description: String {
123x
27
        return String(describing: finder)
123x
28
    }
123x
29
30
}
+
+ + + diff --git a/docs/tests/FinderFactory.swift.html b/docs/tests/FinderFactory.swift.html new file mode 100644 index 000000000..4c1e0f832 --- /dev/null +++ b/docs/tests/FinderFactory.swift.html @@ -0,0 +1,197 @@ + + + +FinderFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "FinderFactory.swift" : 100.00% +

+

(12 of 12 relevant lines covered)

+

RouteComposer/Classes/Factories/FinderFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  FinderFactory.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 08/02/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
/// The `StepAssembly` transforms a `Finder` result as a `Factory` result. It is useful
12
/// when a `UIViewController` instance was built inside of the parent `ContainerFactory`.
13
public struct FinderFactory<F: Finder>: Factory {
14
15
    private let finder: F
16
17
    /// Constructor
18
    ///
19
    /// - Parameters:
20
    ///   - finder: The `Finder` instance to be used by the `Factory`
21
    public init?(finder: F) {
61x
22
        guard !(finder is NilEntity) else {
61x
23
            return nil
2x
24
        }
59x
25
        self.finder = finder
59x
26
    }
59x
27
28
    public func build(with context: F.Context) throws -> F.ViewController {
16x
29
        guard let viewController = finder.findViewController(with: context) else {
16x
30
            throw RoutingError.compositionFailed(.init("\(String(describing: finder)) hasn't found its view controller in the stack."))
1x
31
        }
15x
32
        return viewController
15x
33
    }
16x
34
35
}
+
+ + + diff --git a/docs/tests/GeneralStep.swift.html b/docs/tests/GeneralStep.swift.html new file mode 100644 index 000000000..fa63f5723 --- /dev/null +++ b/docs/tests/GeneralStep.swift.html @@ -0,0 +1,412 @@ + + + +GeneralStep.swift - Slather + + + +
Slather logo
+

+Coverage for "GeneralStep.swift" : 91.67% +

+

(33 of 36 relevant lines covered)

+

RouteComposer/Classes/Steps/GeneralStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-09-17.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// A wrapper for the general steps that can be applied to any `UIViewController`
9
public struct GeneralStep {
10
11
    struct RootViewControllerStep: RoutingStep, PerformableStep {
12
13
        let windowProvider: WindowProvider
14
15
        /// Constructor
16
        init(windowProvider: WindowProvider = KeyWindowProvider()) {
52x
17
            self.windowProvider = windowProvider
52x
18
        }
52x
19
20
        func perform(with context: Any?) throws -> PerformableStepResult {
20x
21
            guard let viewController = windowProvider.window?.rootViewController else {
20x
22
                throw RoutingError.generic(.init("Root view controller was not found."))
!
23
            }
20x
24
            return .success(viewController)
20x
25
        }
20x
26
27
    }
28
29
    struct CurrentViewControllerStep: RoutingStep, PerformableStep {
30
31
        let windowProvider: WindowProvider
32
33
        /// Constructor
34
        init(windowProvider: WindowProvider = KeyWindowProvider()) {
26x
35
            self.windowProvider = windowProvider
26x
36
        }
26x
37
38
        func perform(with context: Any?) throws -> PerformableStepResult {
17x
39
            guard let viewController = windowProvider.window?.topmostViewController else {
17x
40
                throw RoutingError.generic(.init("Topmost view controller was not found."))
!
41
            }
17x
42
            return .success(viewController)
17x
43
        }
17x
44
45
    }
46
47
    struct FinderStep: RoutingStep, PerformableStep {
48
49
        let finder: AnyFinder?
50
51
        init<F: Finder>(finder: F) {
8x
52
            self.finder = FinderBox(finder)
8x
53
        }
8x
54
55
        func perform(with context: Any?) throws -> PerformableStepResult {
6x
56
            guard let viewController = try finder?.findViewController(with: context) else {
6x
57
                throw RoutingError.generic(.init("A view controller of \(String(describing: finder)) was not found."))
!
58
            }
6x
59
            return .success(viewController)
6x
60
        }
6x
61
    }
62
63
    /// Returns the root view controller of the key window.
64
    public static func root<C>(windowProvider: WindowProvider = KeyWindowProvider()) -> DestinationStep<UIViewController, C> {
52x
65
        return DestinationStep(RootViewControllerStep(windowProvider: windowProvider))
52x
66
    }
52x
67
68
    /// Returns the topmost presented view controller.
69
    public static func current<C>(windowProvider: WindowProvider = KeyWindowProvider()) -> DestinationStep<UIViewController, C> {
26x
70
        return DestinationStep(CurrentViewControllerStep(windowProvider: windowProvider))
26x
71
    }
26x
72
73
    /// Returns the resulting view controller of the finder provided.
74
    public static func custom<F: Finder>(using finder: F) -> DestinationStep<F.ViewController, F.Context> {
3x
75
        return DestinationStep(FinderStep(finder: finder))
3x
76
    }
3x
77
78
}
+
+ + + diff --git a/docs/tests/GenericStepAssembly.swift.html b/docs/tests/GenericStepAssembly.swift.html new file mode 100644 index 000000000..45e31b2a9 --- /dev/null +++ b/docs/tests/GenericStepAssembly.swift.html @@ -0,0 +1,257 @@ + + + +GenericStepAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "GenericStepAssembly.swift" : 100.00% +

+

(12 of 12 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/GenericStepAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 31/08/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Abstract builder class that helps to create a `DestinationStep` instance with correct settings.
9
public class GenericStepAssembly<VC: UIViewController, C>: InterceptableStepAssembling {
10
11
    public typealias ViewController = VC
12
13
    public typealias Context = C
14
15
    var taskCollector: TaskCollector = TaskCollector()
16
17
    /// Adds `RoutingInterceptor` instance.
18
    /// This action does not contain type safety checks to avoid complications.
19
    ///
20
    /// - Parameter interceptor: The `RoutingInterceptor` instance to be executed by `Router` before the navigation process
21
    ///   to this step.
22
    public final func adding<RI: RoutingInterceptor>(_ interceptor: RI) -> Self where RI.Context == Context {
17x
23
        taskCollector.add(interceptor)
17x
24
        return self
17x
25
    }
17x
26
27
    /// Adds `ContextTask` instance
28
    ///
29
    /// - Parameter contextTask: The `ContextTask` instance to be applied by a `Router` immediately after it
30
    ///   will find or create `UIViewController`.
31
    public final func adding<CT: ContextTask>(_ contextTask: CT) -> Self
32
            where
33
            CT.ViewController == ViewController, CT.Context == Context {
89x
34
        taskCollector.add(contextTask)
89x
35
        return self
89x
36
    }
89x
37
38
    /// Adds `PostRoutingTask` instance.
39
    /// This action does not contain type safety checks to avoid complications.
40
    ///
41
    /// - Parameter postTask: The `PostRoutingTask` instance to be executed by a `Router` after the navigation process.
42
    public final func adding<PT: PostRoutingTask>(_ postTask: PT) -> Self where PT.Context == Context {
6x
43
        taskCollector.add(postTask)
6x
44
        return self
6x
45
    }
6x
46
47
}
+
+ + + diff --git a/docs/tests/InlineTasks.swift.html b/docs/tests/InlineTasks.swift.html new file mode 100644 index 000000000..1b4614537 --- /dev/null +++ b/docs/tests/InlineTasks.swift.html @@ -0,0 +1,552 @@ + + + +InlineTasks.swift - Slather + + + +
Slather logo
+

+Coverage for "InlineTasks.swift" : 100.00% +

+

(36 of 36 relevant lines covered)

+

RouteComposer/Classes/InlineTasks.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  InlineTasks.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 16/07/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
/// `InlineInterceptor`
12
///
13
/// **NB:** It may be used for the purpose of configuration testing, but then replaced with a strongly typed
14
/// `RoutingInterceptor` instance.
15
public struct InlineInterceptor<C>: RoutingInterceptor {
16
17
    private let prepareBlock: ((_: C) throws -> Void)?
18
19
    private let asyncCompletion: ((_: C, _: @escaping (InterceptorResult) -> Void) -> Void)?
20
21
    private let syncCompletion: ((_: C) -> Void)?
22
23
    /// Constructor
24
    ///
25
    /// - Parameter completion: the block to be called when `InlineInterceptor` will take a control over the navigation process.
26
    ///
27
    ///     **NB** For `Router` to be able to continue navigation process, completion block method **MUST** be called.
28
    public init(prepare: ((_: C) throws -> Void)? = nil, _ completion: @escaping (_: C, _: @escaping (InterceptorResult) -> Void) -> Void) {
1x
29
        self.prepareBlock = prepare
1x
30
        self.asyncCompletion = completion
1x
31
        self.syncCompletion = nil
1x
32
    }
1x
33
34
    /// Constructor
35
    ///
36
    /// - Parameter completion: the block to be called when `InlineInterceptor` will take a control over the navigation process.
37
    ///
38
    ///     **NB** completion method will be called automatically, do not use this constructor if your interceptor
39
    ///     task is asynchronous.
40
    public init(prepare: ((_: C) throws -> Void)? = nil, _ completion: @escaping (_: C) -> Void) {
9x
41
        self.prepareBlock = prepare
9x
42
        self.syncCompletion = completion
9x
43
        self.asyncCompletion = nil
9x
44
    }
9x
45
46
    public func prepare(with context: C) throws {
10x
47
        try prepareBlock?(context)
10x
48
    }
10x
49
50
    public func execute(with context: C, completion: @escaping (InterceptorResult) -> Void) {
7x
51
        if let syncCompletion = syncCompletion {
7x
52
            syncCompletion(context)
6x
53
            completion(.continueRouting)
6x
54
        } else if let asyncCompletion = asyncCompletion {
7x
55
            asyncCompletion(context, completion)
1x
56
        } else {
7x
57
            assertionFailure("The completion block was not set.")
6x
58
            completion(.failure(RoutingError.generic(.init("The completion block was not set."))))
6x
59
        }
7x
60
    }
7x
61
62
}
63
64
/// `InlineContextTask`
65
///
66
/// **NB:** It may be used for the purpose of configuration testing, but then replaced with a strongly typed
67
/// `RoutingInterceptor` instance.
68
public struct InlineContextTask<VC: UIViewController, C>: ContextTask {
69
70
    private let completion: (_: VC, _: C) throws -> Void
71
72
    /// Constructor
73
    ///
74
    /// - Parameter completion: the block to be called when `InlineContextTask` will be applied to the `UIViewController`
75
    ///    instance.
76
    public init(_ completion: @escaping (_: VC, _: C) throws -> Void) {
7x
77
        self.completion = completion
7x
78
    }
7x
79
80
    public func apply(on viewController: VC, with context: C) throws {
9x
81
        try completion(viewController, context)
9x
82
    }
9x
83
84
}
85
86
/// `InlinePostTask` is the inline context task.
87
///
88
/// **NB:** It may be used for the purpose of configuration testing, but then replaced with a strongly typed
89
/// `PostRoutingTask` instance.
90
public struct InlinePostTask<VC: UIViewController, C>: PostRoutingTask {
91
92
    private let completion: (_: VC, _: C, _: [UIViewController]) -> Void
93
94
    /// Constructor
95
    ///
96
    /// - Parameter completion: the block to be called when `InlinePostTask` will be called at the end of the navigation process
97
    ///   process.
98
    public init(_ completion: @escaping (_: VC, _: C, _: [UIViewController]) -> Void) {
9x
99
        self.completion = completion
9x
100
    }
9x
101
102
    public func execute(on viewController: VC, with context: C, routingStack: [UIViewController]) {
11x
103
        completion(viewController, context, routingStack)
11x
104
    }
11x
105
106
}
+
+ + + diff --git a/docs/tests/InstanceFinder.swift.html b/docs/tests/InstanceFinder.swift.html new file mode 100644 index 000000000..41ab40b45 --- /dev/null +++ b/docs/tests/InstanceFinder.swift.html @@ -0,0 +1,157 @@ + + + +InstanceFinder.swift - Slather + + + +
Slather logo
+

+Coverage for "InstanceFinder.swift" : 100.00% +

+

(6 of 6 relevant lines covered)

+

RouteComposer/Classes/Finders/InstanceFinder.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// The `Finder` that provides the `Router` a known instance of the `UIViewController`
10
public struct InstanceFinder<VC: UIViewController, C>: Finder {
11
12
    /// The `UIViewController` instance that `Finder` will provide to the `Router`
13
    private(set) public weak var instance: VC?
14
15
    /// Constructor
16
    ///
17
    /// - Parameters:
18
    ///   - instance: The `UIViewController` instance that `Finder` should provide to the `Router`
19
    public init(instance: VC) {
1x
20
        self.instance = instance
1x
21
    }
1x
22
23
    public func findViewController(with context: C) -> VC? {
1x
24
        return instance
1x
25
    }
1x
26
27
}
+
+ + + diff --git a/docs/tests/InterceptorMultiplexer.swift.html b/docs/tests/InterceptorMultiplexer.swift.html new file mode 100644 index 000000000..7f84dbb91 --- /dev/null +++ b/docs/tests/InterceptorMultiplexer.swift.html @@ -0,0 +1,282 @@ + + + +InterceptorMultiplexer.swift - Slather + + + +
Slather logo
+

+Coverage for "InterceptorMultiplexer.swift" : 86.49% +

+

(32 of 37 relevant lines covered)

+

RouteComposer/Classes/Router/Multiplexers/InterceptorMultiplexer.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 23/01/2018.
3
//
4
5
import Foundation
6
7
struct InterceptorMultiplexer: AnyRoutingInterceptor, MainThreadChecking, CustomStringConvertible {
8
9
    private var interceptors: [AnyRoutingInterceptor]
10
11
    init(_ interceptors: [AnyRoutingInterceptor]) {
24x
12
        self.interceptors = interceptors
24x
13
    }
24x
14
15
    mutating func prepare(with context: Any?) throws {
3x
16
        interceptors = try interceptors.map({
4x
17
            var interceptor = $0
4x
18
            try interceptor.prepare(with: context)
4x
19
            return interceptor
4x
20
        })
4x
21
    }
3x
22
23
    func execute(with context: Any?, completion: @escaping (InterceptorResult) -> Void) {
22x
24
        guard !self.interceptors.isEmpty else {
22x
25
            completion(.continueRouting)
!
26
            return
!
27
        }
22x
28
22x
29
        var interceptors = self.interceptors
22x
30
22x
31
        func runInterceptor(interceptor: AnyRoutingInterceptor) {
42x
32
            self.assertIfNotMainThread()
42x
33
            interceptor.execute(with: context) { result in
42x
34
                self.assertIfNotMainThread()
42x
35
                if case .failure(_) = result {
42x
36
                    completion(result)
2x
37
                } else if interceptors.isEmpty {
42x
38
                    completion(result)
20x
39
                } else {
42x
40
                    runInterceptor(interceptor: interceptors.removeFirst())
22x
41
                }
42x
42
            }
42x
43
        }
42x
44
22x
45
        runInterceptor(interceptor: interceptors.removeFirst())
22x
46
    }
22x
47
48
    var description: String {
!
49
        return String(describing: interceptors)
!
50
    }
!
51
52
}
+
+ + + diff --git a/docs/tests/InterceptorResult.swift.html b/docs/tests/InterceptorResult.swift.html new file mode 100644 index 000000000..b78fccfe3 --- /dev/null +++ b/docs/tests/InterceptorResult.swift.html @@ -0,0 +1,192 @@ + + + +InterceptorResult.swift - Slather + + + +
Slather logo
+

+Coverage for "InterceptorResult.swift" : 0.00% +

+

(0 of 6 relevant lines covered)

+

RouteComposer/Classes/InterceptorResult.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  InterceptorResult.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 23/01/2018.
6
//
7
8
import Foundation
9
10
/// The result of the interceptor's `RoutingInterceptor.execute(...)` method.
11
///
12
/// - continueRouting: Interceptor finished its task with success. The `Router` may continue navigation process.
13
/// - failure: Interceptor finished its task with failure. The `Router` should stop navigation process.
14
public enum InterceptorResult {
15
16
    /// `InterceptorResult` finished its task with success. The `Router` may continue navigation process.
17
    case continueRouting
18
19
    /// `InterceptorResult` finished its task with failure. The `Router` should stop navigation process.
20
    case failure(Error)
21
22
}
23
24
public extension InterceptorResult {
25
26
    /// Returns `true` if `InterceptorResult` is `.continueRouting`
27
    var isSuccessful: Bool {
!
28
        guard case .continueRouting = self else {
!
29
            return false
!
30
        }
!
31
        return true
!
32
    }
!
33
34
}
+
+ + + diff --git a/docs/tests/KeyWindowProvider.swift.html b/docs/tests/KeyWindowProvider.swift.html new file mode 100644 index 000000000..f8d24c410 --- /dev/null +++ b/docs/tests/KeyWindowProvider.swift.html @@ -0,0 +1,137 @@ + + + +KeyWindowProvider.swift - Slather + + + +
Slather logo
+

+Coverage for "KeyWindowProvider.swift" : 77.78% +

+

(7 of 9 relevant lines covered)

+

RouteComposer/Classes/Finders/Stack Iterator/KeyWindowProvider.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Kazaev, Eugene on 2019-02-15.
3
//
4
5
import Foundation
6
7
/// Returns key `UIWindow`
8
public struct KeyWindowProvider: WindowProvider {
9
10
    /// `UIWindow` instance
11
    public var window: UIWindow? {
293x
12
        guard let window = UIApplication.shared.keyWindow else {
293x
13
            assertionFailure("Application does not have a key window.")
!
14
            return nil
!
15
        }
293x
16
        return window
293x
17
    }
293x
18
19
    /// Constructor
20
    public init() {
298x
21
    }
298x
22
23
}
+
+ + + diff --git a/docs/tests/LastStepInChainAssembly.swift.html b/docs/tests/LastStepInChainAssembly.swift.html new file mode 100644 index 000000000..85b931f24 --- /dev/null +++ b/docs/tests/LastStepInChainAssembly.swift.html @@ -0,0 +1,227 @@ + + + +LastStepInChainAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "LastStepInChainAssembly.swift" : 86.36% +

+

(19 of 22 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/LastStepInChainAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 31/08/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Helper class to build a chain of steps. Can not be used directly.
9
public struct LastStepInChainAssembly<ViewController: UIViewController, Context> {
10
11
    let previousSteps: [RoutingStep]
12
13
    init(previousSteps: [RoutingStep]) {
149x
14
        self.previousSteps = previousSteps
149x
15
    }
149x
16
17
    /// Assembles all the provided settings.
18
    ///
19
    /// - Returns: The instance of `DestinationStep` with all the settings provided inside.
20
    public func assemble() -> DestinationStep<ViewController, Context> {
149x
21
        return DestinationStep(chain(previousSteps))
149x
22
    }
149x
23
24
    private func chain(_ steps: [RoutingStep]) -> RoutingStep {
149x
25
        guard let lastStep = steps.last else {
149x
26
            fatalError("No steps provided to chain.")
!
27
        }
149x
28
149x
29
        let firstStep = steps.dropLast().reversed().reduce(lastStep, { (result, currentStep) in
189x
30
            guard var step = currentStep as? BaseStep else {
189x
31
                assertionFailure("\(currentStep) can not be chained to non chainable step \(result)")
!
32
                return currentStep
!
33
            }
189x
34
            step.from(result)
189x
35
            return step
189x
36
        })
189x
37
149x
38
        return firstStep
149x
39
    }
149x
40
41
}
+
+ + + diff --git a/docs/tests/MainThreadChecking.swift.html b/docs/tests/MainThreadChecking.swift.html new file mode 100644 index 000000000..502981dae --- /dev/null +++ b/docs/tests/MainThreadChecking.swift.html @@ -0,0 +1,127 @@ + + + +MainThreadChecking.swift - Slather + + + +
Slather logo
+

+Coverage for "MainThreadChecking.swift" : 57.14% +

+

(4 of 7 relevant lines covered)

+

RouteComposer/Classes/Router/Internal/MainThreadChecking.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-11-12.
3
//
4
5
import Foundation
6
7
protocol MainThreadChecking {
8
9
}
10
11
extension MainThreadChecking {
12
13
    func assertIfNotMainThread(functionName: String = #function, logger: Logger? = nil) {
1050x
14
        if !Thread.isMainThread {
1050x
15
            let errorMessage = "Internal inconsistency: Method \(functionName) requires to be called on the main thread."
!
16
            logger?.log(.error(errorMessage))
!
17
            assertionFailure(errorMessage)
!
18
        }
1050x
19
    }
1050x
20
21
}
+
+ + + diff --git a/docs/tests/NavigationController+Extension.swift.html b/docs/tests/NavigationController+Extension.swift.html new file mode 100644 index 000000000..83535dccf --- /dev/null +++ b/docs/tests/NavigationController+Extension.swift.html @@ -0,0 +1,247 @@ + + + +NavigationController+Extension.swift - Slather + + + +
Slather logo
+

+Coverage for "NavigationController+Extension.swift" : 95.65% +

+

(22 of 23 relevant lines covered)

+

RouteComposer/Classes/Extensions/NavigationController+Extension.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 16/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// - The `UINavigationController` extension is to support the `ContainerViewController` protocol
10
extension UINavigationController: ContainerViewController {
11
12
    public var containedViewControllers: [UIViewController] {
261x
13
        return viewControllers
261x
14
    }
261x
15
16
    public var visibleViewControllers: [UIViewController] {
283x
17
        guard let visibleViewController = visibleViewController else {
283x
18
            return []
!
19
        }
283x
20
        return [visibleViewController]
283x
21
    }
283x
22
23
    public func makeVisible(_ viewController: UIViewController, animated: Bool) {
43x
24
        guard visibleViewController != viewController,
43x
25
              let viewControllerToMakeVisible = containedViewControllers.first(where: { $0 == viewController }) else {
43x
26
            return
33x
27
        }
33x
28
        self.popToViewController(viewControllerToMakeVisible, animated: animated)
10x
29
    }
10x
30
31
    public func replace(containedViewControllers: [UIViewController], animated: Bool, completion: @escaping () -> Void) {
2x
32
        setViewControllers(containedViewControllers, animated: animated)
2x
33
        completion()
2x
34
    }
2x
35
36
}
37
38
/// - The `UINavigationController` extension is to support the `RoutingInterceptable` protocol
39
extension UINavigationController: RoutingInterceptable {
40
41
    public var canBeDismissed: Bool {
92x
42
        return containedViewControllers.canBeDismissed
92x
43
    }
92x
44
45
}
+
+ + + diff --git a/docs/tests/NavigationControllerFactory.swift.html b/docs/tests/NavigationControllerFactory.swift.html new file mode 100644 index 000000000..ad06eb1e6 --- /dev/null +++ b/docs/tests/NavigationControllerFactory.swift.html @@ -0,0 +1,222 @@ + + + +NavigationControllerFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "NavigationControllerFactory.swift" : 78.95% +

+

(15 of 19 relevant lines covered)

+

RouteComposer/Classes/Factories/NavigationControllerFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// The `ContainerFactory` that creates a `UINavigationController` instance.
9
public struct NavigationControllerFactory<C>: SimpleContainerFactory {
10
11
    /// `UINavigationControllerDelegate` reference
12
    private(set) public weak var delegate: UINavigationControllerDelegate?
13
14
    /// Block to configure `UINavigationController`
15
    public let configuration: ((_: UINavigationController) -> Void)?
16
17
    /// Constructor
18
    public init(delegate: UINavigationControllerDelegate? = nil,
19
                configuration: ((_: UINavigationController) -> Void)? = nil) {
20x
20
        self.delegate = delegate
20x
21
        self.configuration = configuration
20x
22
    }
20x
23
24
    public func build(with context: C, integrating viewControllers: [UIViewController]) throws -> UINavigationController {
10x
25
        guard !viewControllers.isEmpty else {
10x
26
            throw RoutingError.compositionFailed(.init("Unable to build UINavigationController due to 0 amount " +
!
27
                    "of the children view controllers"))
!
28
        }
10x
29
        let navigationController = UINavigationController()
10x
30
        if let delegate = delegate {
10x
31
            navigationController.delegate = delegate
!
32
        }
10x
33
        if let configuration = configuration {
10x
34
            configuration(navigationController)
!
35
        }
10x
36
        navigationController.viewControllers = viewControllers
10x
37
        return navigationController
10x
38
    }
10x
39
40
}
+
+ + + diff --git a/docs/tests/NavigationControllerStep.swift.html b/docs/tests/NavigationControllerStep.swift.html new file mode 100644 index 000000000..37ac3fca8 --- /dev/null +++ b/docs/tests/NavigationControllerStep.swift.html @@ -0,0 +1,102 @@ + + + +NavigationControllerStep.swift - Slather + + + +
Slather logo
+

+Coverage for "NavigationControllerStep.swift" : 100.00% +

+

(3 of 3 relevant lines covered)

+

RouteComposer/Classes/Steps/NavigationControllerStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// Default navigation container step
9
public class NavigationControllerStep<Context>: SingleContainerStep<NilFinder<UINavigationController, Context>, NavigationControllerFactory<Context>> {
10
11
    /// Constructor
12
    public init() {
13x
13
        super.init(finder: NilFinder(), factory: NavigationControllerFactory())
13x
14
    }
13x
15
16
}
+
+ + + diff --git a/docs/tests/NavigationDelayInterceptor.swift.html b/docs/tests/NavigationDelayInterceptor.swift.html new file mode 100644 index 000000000..b48856878 --- /dev/null +++ b/docs/tests/NavigationDelayInterceptor.swift.html @@ -0,0 +1,417 @@ + + + +NavigationDelayInterceptor.swift - Slather + + + +
Slather logo
+

+Coverage for "NavigationDelayInterceptor.swift" : 96.77% +

+

(30 of 31 relevant lines covered)

+

RouteComposer/Classes/Extra/NavigationDelayInterceptor.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-03-01.
3
// Copyright © 2019 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
8
/// `NavigationDelayInterceptor` delays the router from starting the navigation, while any view controllers in the
9
/// stack are being presented or dismissed. In case your app has some other navigation instruments rather than
10
/// `RouteComposer` or you have a situation when a few routers work simultaneously, add it to your router to avoid
11
/// the router not being able to navigate to the destination because a view controller in the stack is
12
/// being presented or dismissed.
13
///
14
/// *NB: `UIKit` does not allow simultaneous changes in `UIViewController` stack. The `.wait` strategy does not
15
/// guarantee 100% protection from all possible situations. Code must be written in a way that avoids such
16
/// situations. The `.wait` strategy can be used only as a temporary solution.*
17
public struct NavigationDelayingInterceptor: RoutingInterceptor {
18
19
    /// The strategy to be used by `NavigationDelayInterceptor`
20
    ///
21
    /// - wait: Wait while some `UIViewController` is being presented or dismissed.
22
    /// - abort:  Abort tha navigation if some `UIViewController` is being presented or dismissed.
23
    public enum Strategy {
24
25
        /// Abort tha navigation if some `UIViewController` is being presented or dismissed.
26
        case abort
27
28
        /// Wait while some `UIViewController` is being presented or dismissed.
29
        case wait
30
31
    }
32
33
    let windowProvider: WindowProvider
34
35
    let logger: Logger?
36
37
    let strategy: Strategy
38
39
    /// Constructor
40
    ///
41
    /// - Parameters:
42
    ///   - windowProvider: `WindowProvider` instance.
43
    ///   - strategy: Type of `Strategy` to be used.
44
    ///   - logger: `Logger` instance.
45
    public init(windowProvider: WindowProvider = KeyWindowProvider(), strategy: Strategy = .abort, logger: Logger? = nil) {
9x
46
        self.windowProvider = windowProvider
9x
47
        self.logger = logger
9x
48
        self.strategy = strategy
9x
49
    }
9x
50
51
    public func execute(with context: Any?, completion: @escaping (InterceptorResult) -> Void) {
84x
52
        guard let topmostViewController = getTopmostViewController(),
84x
53
              topmostViewController.isBeingDismissed || topmostViewController.isBeingPresented else {
84x
54
            completion(.continueRouting)
80x
55
            return
80x
56
        }
80x
57
4x
58
        if strategy == .wait {
4x
59
            logger?.log(.info("\(topmostViewController) is changing its state. Navigation has been delayed."))
4x
60
            let deadline = DispatchTime.now() + .milliseconds(100)
4x
61
            DispatchQueue.main.asyncAfter(deadline: deadline) {
4x
62
                self.execute(with: context, completion: completion)
4x
63
            }
4x
64
        } else {
4x
65
            completion(.failure(RoutingError.compositionFailed(.init("\(topmostViewController) is changing its state. Navigation has been aborted."))))
!
66
        }
4x
67
    }
4x
68
69
    private func getTopmostViewController() -> UIViewController? {
84x
70
        var topmostViewController = windowProvider.window?.rootViewController
84x
71
84x
72
        while let presentedViewController = topmostViewController?.presentedViewController {
84x
73
            topmostViewController = presentedViewController
34x
74
        }
84x
75
84x
76
        return topmostViewController
84x
77
    }
84x
78
79
}
+
+ + + diff --git a/docs/tests/NilFactory.swift.html b/docs/tests/NilFactory.swift.html new file mode 100644 index 000000000..a4f860d4b --- /dev/null +++ b/docs/tests/NilFactory.swift.html @@ -0,0 +1,172 @@ + + + +NilFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "NilFactory.swift" : 100.00% +

+

(8 of 8 relevant lines covered)

+

RouteComposer/Classes/Factories/NilFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  NilFactory.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 08/02/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
/// The dummy struct used to represent the `Factory` that does not build anything.
12
/// Its only purpose is to provide the type safety checks for the `StepAssembly`.
13
///
14
/// For example, the `UIViewController` of the step was already loaded and integrated into a stack by a
15
/// storyboard in a previous step.
16
public struct NilFactory<VC: UIViewController, C>: Factory, NilEntity {
17
18
    /// Constructor
19
    public init() {
54x
20
    }
54x
21
22
    public func prepare(with context: C) throws {
2x
23
        throw RoutingError.compositionFailed(.init("This factory can not build any UIViewController."))
2x
24
    }
2x
25
26
    public func build(with context: C) throws -> VC {
1x
27
        throw RoutingError.compositionFailed(.init("This factory can not build any UIViewController."))
1x
28
    }
1x
29
30
}
+
+ + + diff --git a/docs/tests/NilFinder.swift.html b/docs/tests/NilFinder.swift.html new file mode 100644 index 000000000..2a1dfc941 --- /dev/null +++ b/docs/tests/NilFinder.swift.html @@ -0,0 +1,157 @@ + + + +NilFinder.swift - Slather + + + +
Slather logo
+

+Coverage for "NilFinder.swift" : 100.00% +

+

(5 of 5 relevant lines covered)

+

RouteComposer/Classes/Finders/NilFinder.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 20/01/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Dummy struct used to represent that nothing should be found in a view controller stack
9
/// and a `UIViewController` should always be created from scratch.
10
/// Its only purpose is to provide type safety checks for `StepAssembly`.
11
///
12
/// For example, `UIViewController` of this step was already loaded and integrated into a stack by a storyboard.
13
public struct NilFinder<VC: UIViewController, C>: Finder, NilEntity {
14
15
    /// Constructor
16
    public init() {
44x
17
    }
44x
18
19
    /// `Finder` method empty implementation.
20
    ///
21
    /// - Parameter context: A context instance provided.
22
    /// - Returns: always `nil`.
23
    public func findViewController(with context: C) -> VC? {
1x
24
        return nil
1x
25
    }
1x
26
27
}
+
+ + + diff --git a/docs/tests/PostRoutingTask.swift.html b/docs/tests/PostRoutingTask.swift.html new file mode 100644 index 000000000..d282c5e14 --- /dev/null +++ b/docs/tests/PostRoutingTask.swift.html @@ -0,0 +1,292 @@ + + + +PostRoutingTask.swift - Slather + + + +
Slather logo
+

+Coverage for "PostRoutingTask.swift" : 0.00% +

+

(0 of 6 relevant lines covered)

+

RouteComposer/Classes/PostRoutingTask.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 17/01/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// The task to be executed after navigation process happened.
9
public protocol PostRoutingTask {
10
11
    /// `UIViewController` type associated with this `PostRoutingTask`
12
    associatedtype ViewController: UIViewController
13
14
    /// `Context` type associated with this `PostRoutingTask`
15
    associatedtype Context
16
17
    /// Method to be executed by the `Router` after all the view controllers have been built into the stack.
18
    ///
19
    /// - Parameters:
20
    ///   - viewController: The `UIViewController` instance that this post-task has been attached to
21
    ///   - context: The `Context` instance provided to the `Router`
22
    ///   - routingStack: An array of all the view controllers that been built by the `Router` to
23
    ///     reach the final destination
24
    func execute(on viewController: ViewController, with context: Context, routingStack: [UIViewController])
25
26
}
27
28
public extension PostRoutingTask where Context == Any? {
29
30
    /// Method to be executed by the `Router` after all the view controllers have been built into the stack.
31
    ///
32
    /// - Parameters:
33
    ///   - viewController: The `UIViewController` instance that this post-task has been attached to
34
    ///   - routingStack: An array of all the view controllers that been built by the `Router` to
35
    ///     reach the final destination
36
    func execute(on viewController: ViewController, routingStack: [UIViewController]) {
!
37
        execute(on: viewController, with: nil, routingStack: routingStack)
!
38
    }
!
39
40
}
41
42
public extension PostRoutingTask where Context == Void {
43
44
    /// Method to be executed by the `Router` after all the view controllers have been built into the stack.
45
    ///
46
    /// - Parameters:
47
    ///   - viewController: The `UIViewController` instance that this post-task has been attached to
48
    ///   - routingStack: An array of all the view controllers that been built by the `Router` to
49
    ///     reach the final destination
50
    func execute(on viewController: ViewController, routingStack: [UIViewController]) {
!
51
        execute(on: viewController, with: (), routingStack: routingStack)
!
52
    }
!
53
54
}
+
+ + + diff --git a/docs/tests/PostRoutingTaskBox.swift.html b/docs/tests/PostRoutingTaskBox.swift.html new file mode 100644 index 000000000..2a43c8c89 --- /dev/null +++ b/docs/tests/PostRoutingTaskBox.swift.html @@ -0,0 +1,192 @@ + + + +PostRoutingTaskBox.swift - Slather + + + +
Slather logo
+

+Coverage for "PostRoutingTaskBox.swift" : 88.89% +

+

(16 of 18 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/PostRoutingTaskBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
struct PostRoutingTaskBox<PT: PostRoutingTask>: AnyPostRoutingTask, MainThreadChecking, CustomStringConvertible {
8
9
    let postRoutingTask: PT
10
11
    init(_ postRoutingTask: PT) {
9x
12
        self.postRoutingTask = postRoutingTask
9x
13
    }
9x
14
15
    func execute(on viewController: UIViewController,
16
                 with context: Any?,
17
                 routingStack: [UIViewController]) throws {
12x
18
        guard let typedViewController = viewController as? PT.ViewController else {
12x
19
            throw RoutingError.typeMismatch(PT.ViewController.self, .init("\(String(describing: postRoutingTask.self)) does not support" +
!
20
                    " \(String(describing: viewController.self))."))
!
21
        }
12x
22
        guard let typedDestination = Any?.some(context as Any) as? PT.Context else {
12x
23
            throw RoutingError.typeMismatch(PT.Context.self, .init("\(String(describing: postRoutingTask.self)) does not accept" +
1x
24
                    "  \(String(describing: context.self)) as a context."))
1x
25
        }
11x
26
        assertIfNotMainThread()
11x
27
        postRoutingTask.execute(on: typedViewController, with: typedDestination, routingStack: routingStack)
11x
28
    }
11x
29
30
    var description: String {
1x
31
        return String(describing: postRoutingTask)
1x
32
    }
1x
33
34
}
+
+ + + diff --git a/docs/tests/PostRoutingTaskMultiplexer.swift.html b/docs/tests/PostRoutingTaskMultiplexer.swift.html new file mode 100644 index 000000000..183cfcdae --- /dev/null +++ b/docs/tests/PostRoutingTaskMultiplexer.swift.html @@ -0,0 +1,142 @@ + + + +PostRoutingTaskMultiplexer.swift - Slather + + + +
Slather logo
+

+Coverage for "PostRoutingTaskMultiplexer.swift" : 66.67% +

+

(6 of 9 relevant lines covered)

+

RouteComposer/Classes/Router/Multiplexers/PostRoutingTaskMultiplexer.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 23/01/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
struct PostRoutingTaskMultiplexer: AnyPostRoutingTask, CustomStringConvertible {
9
10
    private let tasks: [AnyPostRoutingTask]
11
12
    init(_ tasks: [AnyPostRoutingTask]) {
1x
13
        self.tasks = tasks
1x
14
    }
1x
15
16
    func execute(on viewController: UIViewController, with context: Any?, routingStack: [UIViewController]) throws {
1x
17
        try tasks.forEach({ try $0.execute(on: viewController, with: context, routingStack: routingStack) })
1x
18
    }
1x
19
20
    var description: String {
!
21
        return String(describing: tasks)
!
22
    }
!
23
24
}
+
+ + + diff --git a/docs/tests/PreparableEntity.swift.html b/docs/tests/PreparableEntity.swift.html new file mode 100644 index 000000000..2f7e6cbdb --- /dev/null +++ b/docs/tests/PreparableEntity.swift.html @@ -0,0 +1,132 @@ + + + +PreparableEntity.swift - Slather + + + +
Slather logo
+

+Coverage for "PreparableEntity.swift" : 66.67% +

+

(4 of 6 relevant lines covered)

+

RouteComposer/Classes/Router/Internal/PreparableEntity.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-11-06.
3
//
4
5
import Foundation
6
7
protocol PreparableEntity {
8
9
    var isPrepared: Bool { get }
10
11
}
12
13
extension PreparableEntity {
14
15
    func assertIfNotPrepared() {
326x
16
        if !isPrepared {
326x
17
            assertionFailure("Internal inconsistency: prepare(with:) method has never been " +
!
18
                    "called for \(String(describing: self)).")
!
19
        }
326x
20
    }
326x
21
22
}
+
+ + + diff --git a/docs/tests/PresentingFinder.swift.html b/docs/tests/PresentingFinder.swift.html new file mode 100644 index 000000000..ce93b1067 --- /dev/null +++ b/docs/tests/PresentingFinder.swift.html @@ -0,0 +1,147 @@ + + + +PresentingFinder.swift - Slather + + + +
Slather logo
+

+Coverage for "PresentingFinder.swift" : 100.00% +

+

(6 of 6 relevant lines covered)

+

RouteComposer/Classes/Extra/PresentingFinder.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-03-19.
3
// Copyright © 2019 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// `PresentingFinder` returns the presenting `UIViewController` of the topmost one in current stack.
10
public struct PresentingFinder<C>: Finder {
11
12
    let windowProvider: WindowProvider
13
14
    /// Constructor
15
    ///
16
    /// - Parameter windowProvider: `WindowProvider` instance.
17
    public init(windowProvider: WindowProvider = KeyWindowProvider()) {
3x
18
        self.windowProvider = windowProvider
3x
19
    }
3x
20
21
    public func findViewController(with context: C) -> UIViewController? {
3x
22
        return windowProvider.window?.topmostViewController?.presentingViewController
3x
23
    }
3x
24
25
}
+
+ + + diff --git a/docs/tests/Router.swift.html b/docs/tests/Router.swift.html new file mode 100644 index 000000000..ede6b5a46 --- /dev/null +++ b/docs/tests/Router.swift.html @@ -0,0 +1,282 @@ + + + +Router.swift - Slather + + + +
Slather logo
+

+Coverage for "Router.swift" : 50.00% +

+

(3 of 6 relevant lines covered)

+

RouteComposer/Classes/Router.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
import Foundation
8
9
/// Base router protocol.
10
public protocol Router {
11
12
    /// Navigates an application to the view controller configured in `DestinationStep` with the `Context` provided.
13
    ///
14
    /// - Parameters:
15
    ///   - step: `DestinationStep` instance.
16
    ///   - context: `Context` instance.
17
    ///   - animated: if true - the navigation should be animated where it is possible.
18
    ///   - completion: completion block.
19
    func navigate<ViewController: UIViewController, Context>(to step: DestinationStep<ViewController, Context>,
20
                                                             with context: Context,
21
                                                             animated: Bool,
22
                                                             completion: ((_: RoutingResult) -> Void)?) throws
23
24
}
25
26
public extension Router {
27
28
    /// Navigates an application to the view controller configured in `DestinationStep` with the `Context` set to `Any?`.
29
    ///
30
    /// - Parameters:
31
    ///   - step: `DestinationStep` instance.
32
    ///   - animated: if true - the navigation should be animated where it is possible.
33
    ///   - completion: completion block.
34
    func navigate<ViewController: UIViewController>(to step: DestinationStep<ViewController, Any?>,
35
                                                    animated: Bool,
36
                                                    completion: ((_: RoutingResult) -> Void)?) throws {
1x
37
        try navigate(to: step, with: nil, animated: animated, completion: completion)
1x
38
    }
1x
39
40
    /// Navigates an application to the view controller configured in `DestinationStep` with the `Context` set to `Void`.
41
    ///
42
    /// - Parameters:
43
    ///   - step: `DestinationStep` instance.
44
    ///   - animated: if true - the navigation should be animated where it is possible.
45
    ///   - completion: completion block.
46
    func navigate<ViewController: UIViewController>(to step: DestinationStep<ViewController, Void>,
47
                                                    animated: Bool,
48
                                                    completion: ((_: RoutingResult) -> Void)?) throws {
!
49
        try navigate(to: step, with: (), animated: animated, completion: completion)
!
50
    }
!
51
52
}
+
+ + + diff --git a/docs/tests/RoutingError.swift.html b/docs/tests/RoutingError.swift.html new file mode 100644 index 000000000..632e1ef8a --- /dev/null +++ b/docs/tests/RoutingError.swift.html @@ -0,0 +1,327 @@ + + + +RoutingError.swift - Slather + + + +
Slather logo
+

+Coverage for "RoutingError.swift" : 16.00% +

+

(4 of 25 relevant lines covered)

+

RouteComposer/Classes/RoutingError.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 26/02/2018.
3
//
4
5
import Foundation
6
7
/// Routing `Error` representation
8
///
9
/// - message: Message describing an error that happened
10
public enum RoutingError: Error, CustomStringConvertible {
11
12
    /// Error context holder
13
    public struct Context: CustomStringConvertible {
14
15
        ///  Message describing error that happened
16
        public let debugDescription: String
17
18
        /// Underlying error if present
19
        public let underlyingError: Error?
20
21
        /// Constructor
22
        public init(_ debugDescription: String, underlyingError: Error? = nil) {
28x
23
            self.debugDescription = debugDescription
28x
24
            self.underlyingError = underlyingError
28x
25
        }
28x
26
27
        public var description: String {
!
28
            guard !debugDescription.isEmpty else {
!
29
                return debugDescription
!
30
            }
!
31
!
32
            guard let underlyingError = underlyingError else {
!
33
                return "No valuable information provided"
!
34
            }
!
35
!
36
            return (underlyingError as CustomStringConvertible).description
!
37
        }
!
38
39
    }
40
41
    /// Type mismatch error
42
    case typeMismatch(Any.Type, RoutingError.Context)
43
44
    /// The view controllers stack integration failed
45
    case compositionFailed(RoutingError.Context)
46
47
    /// Message describing error that happened
48
    case generic(RoutingError.Context)
49
50
    public var description: String {
!
51
        switch self {
!
52
        case .typeMismatch(_, let context):
!
53
            return "Type Mismatch Error: \(context.description)"
!
54
        case .compositionFailed(let context):
!
55
            return "Composition Failed Error: \(context.description)"
!
56
        case .generic(let context):
!
57
            return "Generic Error: \(context.description)"
!
58
        }
!
59
    }
!
60
61
}
+
+ + + diff --git a/docs/tests/RoutingInterceptor.swift.html b/docs/tests/RoutingInterceptor.swift.html new file mode 100644 index 000000000..e7c43a5c5 --- /dev/null +++ b/docs/tests/RoutingInterceptor.swift.html @@ -0,0 +1,527 @@ + + + +RoutingInterceptor.swift - Slather + + + +
Slather logo
+

+Coverage for "RoutingInterceptor.swift" : 20.00% +

+

(3 of 15 relevant lines covered)

+

RouteComposer/Classes/RoutingInterceptor.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 17/01/2018.
3
//
4
5
import Foundation
6
7
/// `RoutingInterceptor` is called before the actual navigation process happens.
8
/// e.g. user should be logged in.
9
///
10
/// ### NB
11
/// Interceptor is an asynchronous action. For the `Router` to continue the navigation process, the `completion` block of the interceptor's
12
/// execute method **MUST** be called.
13
/// Otherwise, the `Router` will stay in a limbo state waiting for the interceptor to finish its action.
14
public protocol RoutingInterceptor {
15
16
    /// `Context` type associated with `RoutingInterceptor`
17
    associatedtype Context
18
19
    /// The `Router` will call this method before the navigation process. If `RoutingInterceptor` is not able to allow
20
    /// the navigation process to start it can stop `Router` by throwing an exception.
21
    ///
22
    /// - Parameters:
23
    ///   - context: The `Context` instance that is provided to the `Router`.
24
    /// - Throws: The `RoutingError` if the `RoutingInterceptor` cannot prepare itself or if the navigation process cannot start
25
    ///   with the `Context` instance provided.
26
    mutating func prepare(with context: Context) throws
27
28
    /// Method that will be called by `Router` to start interceptor.
29
    ///
30
    /// - Parameters:
31
    ///   - context: `Context` instance provided to the `Router`
32
    ///   - completion: Completion block with a result.
33
    ///
34
    /// ###NB
35
    /// For the `Router` to continue the navigation process, the `completion` block of interceptor **MUST** be called
36
    /// by the implementation of this method.
37
    /// Otherwise `Router` will stay in limbo waiting for `RoutingInterceptor` to finish its action.
38
    func execute(with context: Context, completion: @escaping (_: InterceptorResult) -> Void)
39
40
}
41
42
public extension RoutingInterceptor {
43
44
    /// Default implementation does nothing.
45
    func prepare(with context: Context) throws {
98x
46
98x
47
    }
98x
48
49
}
50
51
public extension RoutingInterceptor where Context == Any? {
52
53
    /// The `Router` will call this method before the navigation process. If `RoutingInterceptor` is not able to allow
54
    /// the navigation process to start it can stop `Router` by throwing an exception.
55
    ///
56
    /// - Throws: The `RoutingError` if the `RoutingInterceptor` cannot prepare itself or if the navigation process cannot start
57
    ///   with the `Context` instance provided.
58
    mutating func prepare() throws {
!
59
        try prepare(with: nil)
!
60
    }
!
61
62
    /// Method that will be called by `Router` to start interceptor.
63
    ///
64
    /// - Parameters:
65
    ///   - completion: Completion block with a result.
66
    ///
67
    /// ###NB
68
    /// For the `Router` to continue the navigation process, the `completion` block of interceptor **MUST** be called
69
    /// by the implementation of this method.
70
    /// Otherwise `Router` will stay in limbo waiting for `RoutingInterceptor` to finish its action.
71
    func execute(completion: @escaping (_: InterceptorResult) -> Void) {
!
72
        execute(with: nil, completion: completion)
!
73
    }
!
74
75
}
76
77
public extension RoutingInterceptor where Context == Void {
78
79
    /// The `Router` will call this method before the navigation process. If `RoutingInterceptor` is not able to allow
80
    /// the navigation process to start it can stop `Router` by throwing an exception.
81
    ///
82
    /// - Throws: The `RoutingError` if the `RoutingInterceptor` cannot prepare itself or if the navigation process cannot start
83
    ///   with the `Context` instance provided.
84
    mutating func prepare() throws {
!
85
        try prepare(with: ())
!
86
    }
!
87
88
    /// Method that will be called by `Router` to start interceptor.
89
    ///
90
    /// - Parameters:
91
    ///   - completion: Completion block with a result.
92
    ///
93
    /// ###NB
94
    /// For the `Router` to continue the navigation process, the `completion` block of interceptor **MUST** be called
95
    /// by the implementation of this method.
96
    /// Otherwise `Router` will stay in limbo waiting for `RoutingInterceptor` to finish its action.
97
    func execute(completion: @escaping (_: InterceptorResult) -> Void) {
!
98
        execute(with: (), completion: completion)
!
99
    }
!
100
101
}
+
+ + + diff --git a/docs/tests/RoutingInterceptorBox.swift.html b/docs/tests/RoutingInterceptorBox.swift.html new file mode 100644 index 000000000..981b62ee4 --- /dev/null +++ b/docs/tests/RoutingInterceptorBox.swift.html @@ -0,0 +1,247 @@ + + + +RoutingInterceptorBox.swift - Slather + + + +
Slather logo
+

+Coverage for "RoutingInterceptorBox.swift" : 92.86% +

+

(26 of 28 relevant lines covered)

+

RouteComposer/Classes/Router/Type Erasure/Boxes/RoutingInterceptorBox.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2019-02-27.
3
//
4
5
import Foundation
6
7
struct RoutingInterceptorBox<RI: RoutingInterceptor>: AnyRoutingInterceptor, PreparableEntity, CustomStringConvertible, MainThreadChecking {
8
9
    var routingInterceptor: RI
10
11
    var isPrepared = false
12
13
    init(_ routingInterceptor: RI) {
33x
14
        self.routingInterceptor = routingInterceptor
33x
15
    }
33x
16
17
    mutating func prepare(with context: Any?) throws {
109x
18
        guard let typedDestination = Any?.some(context as Any) as? RI.Context else {
109x
19
            throw RoutingError.typeMismatch(RI.Context.self, .init("\(String(describing: routingInterceptor.self)) does " +
!
20
                    "not accept \(String(describing: context.self)) as a context."))
!
21
        }
109x
22
109x
23
        try self.routingInterceptor.prepare(with: typedDestination)
109x
24
        isPrepared = true
109x
25
    }
109x
26
27
    func execute(with context: Any?, completion: @escaping (InterceptorResult) -> Void) {
103x
28
        guard let typedDestination = Any?.some(context as Any) as? RI.Context else {
103x
29
            completion(.failure(RoutingError.typeMismatch(RI.Context.self, .init("\(String(describing: routingInterceptor.self)) does " +
1x
30
                    "not accept \(String(describing: context.self)) as a context."))))
1x
31
            return
1x
32
        }
102x
33
        assertIfNotPrepared()
102x
34
        assertIfNotMainThread()
102x
35
        routingInterceptor.execute(with: typedDestination) { result in
102x
36
            self.assertIfNotMainThread()
102x
37
            completion(result)
102x
38
        }
102x
39
    }
102x
40
41
    var description: String {
1x
42
        return String(describing: routingInterceptor)
1x
43
    }
1x
44
45
}
+
+ + + diff --git a/docs/tests/RoutingResult.swift.html b/docs/tests/RoutingResult.swift.html new file mode 100644 index 000000000..41bce6877 --- /dev/null +++ b/docs/tests/RoutingResult.swift.html @@ -0,0 +1,182 @@ + + + +RoutingResult.swift - Slather + + + +
Slather logo
+

+Coverage for "RoutingResult.swift" : 100.00% +

+

(6 of 6 relevant lines covered)

+

RouteComposer/Classes/RoutingResult.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 19/12/2017.
3
// Copyright (c) 2017 HBC Tech. All rights reserved.
4
//
5
6
import Foundation
7
8
/// The result of the navigation process
9
///
10
/// - success: The request to process the navigation resulted in a successful navigation to the destination.
11
/// - failure: The request to process the navigation was not successful.
12
public enum RoutingResult {
13
14
    /// The request to process the navigation resulted in a successful navigation to the destination.
15
    case success
16
17
    /// The request to process the navigation was not successful.
18
    case failure(Error)
19
20
}
21
22
public extension RoutingResult {
23
24
    /// Returns `true` if `RoutingResult` is `success`
25
    var isSuccessful: Bool {
13x
26
        guard case .success = self else {
13x
27
            return false
2x
28
        }
11x
29
        return true
11x
30
    }
13x
31
32
}
+
+ + + diff --git a/docs/tests/SearchOptions.swift.html b/docs/tests/SearchOptions.swift.html new file mode 100644 index 000000000..f67321018 --- /dev/null +++ b/docs/tests/SearchOptions.swift.html @@ -0,0 +1,407 @@ + + + +SearchOptions.swift - Slather + + + +
Slather logo
+

+Coverage for "SearchOptions.swift" : 79.17% +

+

(19 of 24 relevant lines covered)

+

RouteComposer/Classes/SearchOptions.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 04/09/2018.
3
//
4
5
import Foundation
6
7
/// A set of options for the `findViewController` method
8
public struct SearchOptions: OptionSet, CaseIterable, CustomStringConvertible {
9
10
    public let rawValue: Int
11
12
    public init(rawValue: Int) {
17700x
13
        self.rawValue = rawValue
17700x
14
    }
17700x
15
16
    /// Compare to a view controller provided
17
    public static let current = SearchOptions(rawValue: 1 << 0)
18
19
    /// If a view controller is a container, search in its visible view controllers
20
    public static let visible = SearchOptions(rawValue: 1 << 1)
21
22
    /// If a view controller is a container, search in all the view controllers it contains
23
    public static let contained = SearchOptions(rawValue: 1 << 2)
24
25
    /// Start search from the view controller provided and search in all view controllers it presented
26
    public static let presented = SearchOptions(rawValue: 1 << 3)
27
28
    /// Start search from the view controller provided and search in all view controllers that are presenting it
29
    public static let presenting = SearchOptions(rawValue: 1 << 4)
30
31
    /// Start search from the view controller provided and search in all its parent view controllers
32
    public static let parent = SearchOptions(rawValue: 1 << 5)
33
34
    /// If a view controller is a container, search in all the view controllers it contains
35
    public static let currentAllStack: SearchOptions = [.current, .contained]
36
37
    /// If a view controller is a container, search in all visible view controllers it contains
38
    public static let currentVisibleOnly: SearchOptions = [.current, .visible]
39
40
    /// Iterate through the all visible view controllers in the stack.
41
    public static let allVisible: SearchOptions = [.currentVisibleOnly, .presented, .presenting]
42
43
    /// Iterate through the all view controllers in the stack.
44
    public static let fullStack: SearchOptions = [.current, .contained, .presented, .presenting]
45
46
    /// Iterate through the all view controllers on the current level and all the view controllers
47
    /// presented from the current level.
48
    public static let currentAndUp: SearchOptions = [.currentAllStack, .presented]
49
50
    /// Iterate through the all view controllers on the current level and all the view controllers
51
    /// that are presenting the current level.
52
    public static let currentAndDown: SearchOptions = [.currentAllStack, .presenting]
53
54
    public static var allCases: [SearchOptions] {
!
55
        return [.current, .visible, .contained, .presented, .presenting, .parent]
!
56
    }
!
57
58
    public var description: String {
191x
59
        return [SearchOptions.current, .visible, .contained, .presented, .presenting, .parent].compactMap({ option in
1140x
60
            guard self.contains(option) else {
1140x
61
                return nil
471x
62
            }
675x
63
            switch option {
675x
64
            case .current: return "current"
675x
65
            case .visible: return "visible"
675x
66
            case .contained: return "contained"
675x
67
            case .presented: return "presented"
675x
68
            case .presenting: return "presenting"
675x
69
            case .parent: return "parent"
675x
70
            default:
675x
71
                assertionFailure("Unknown SearchOptions")
!
72
                return nil
!
73
            }
675x
74
        }).joined(separator: ", ")
675x
75
    }
191x
76
77
}
+
+ + + diff --git a/docs/tests/SimpleContainerFactory.swift.html b/docs/tests/SimpleContainerFactory.swift.html new file mode 100644 index 000000000..5789bcc7a --- /dev/null +++ b/docs/tests/SimpleContainerFactory.swift.html @@ -0,0 +1,207 @@ + + + +SimpleContainerFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "SimpleContainerFactory.swift" : 100.00% +

+

(4 of 4 relevant lines covered)

+

RouteComposer/Classes/Factories/SimpleContainerFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 07/09/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// A helper protocol to the `ContainerFactory` protocol. If a container does not need to deal with the children view
9
/// controller creation, `SimpleContainerFactory` will handle integration of the children view controllers.
10
public protocol SimpleContainerFactory: ContainerFactory {
11
12
    /// Type of `UIViewController` that `SimpleContainerFactory` can build
13
    associatedtype ViewController
14
15
    /// `Context` to be passed into `UIViewController`
16
    associatedtype Context
17
18
    /// Builds a `UIViewController` that will be integrated into the stack
19
    ///
20
    /// Parameters:
21
    ///   - context: A `Context` instance provided to the `Router`.
22
    ///   - viewControllers: `UIViewController` instances to be integrated into the container as children view controllers
23
    /// - Returns: The built `UIViewController` container instance.
24
    /// - Throws: The `RoutingError` if the build does not succeed.
25
    func build(with context: Context, integrating viewControllers: [UIViewController]) throws -> ViewController
26
27
}
28
29
public extension SimpleContainerFactory {
30
31
    /// Default implementation of the `ContainerFactory`'s `build` method
32
    func build(with context: Context, integrating coordinator: ChildCoordinator<Context>) throws -> ViewController {
32x
33
        let viewControllers = try coordinator.build(with: context)
32x
34
        return try build(with: context, integrating: viewControllers)
32x
35
    }
32x
36
37
}
+
+ + + diff --git a/docs/tests/SingleContainerStep.swift.html b/docs/tests/SingleContainerStep.swift.html new file mode 100644 index 000000000..eeff2bad9 --- /dev/null +++ b/docs/tests/SingleContainerStep.swift.html @@ -0,0 +1,472 @@ + + + +SingleContainerStep.swift - Slather + + + +
Slather logo
+

+Coverage for "SingleContainerStep.swift" : 35.29% +

+

(12 of 34 relevant lines covered)

+

RouteComposer/Classes/Steps/SingleContainerStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 25/07/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// A simple class that produces an intermediate `ActionToStepIntegrator` describing a container view controller.
9
public class SingleContainerStep<F: Finder, FC: ContainerFactory>: ActionToStepIntegrator<F.ViewController, F.Context>
10
        where
11
        F.ViewController == FC.ViewController, F.Context == FC.Context {
12
13
    let finder: F
14
15
    let factory: FC
16
17
    final class UnsafeWrapper<VC: UIViewController, C, F: Finder, FC: ContainerFactory>: ActionToStepIntegrator<VC, C>
18
            where
19
            F.ViewController == FC.ViewController, F.Context == FC.Context {
20
21
        let step: SingleContainerStep<F, FC>
22
23
        init(step: SingleContainerStep<F, FC>) {
!
24
            self.step = step
!
25
            super.init(taskCollector: step.taskCollector)
!
26
        }
!
27
28
        override func routingStep<A: Action>(with action: A) -> RoutingStep {
!
29
            return step.routingStep(with: action)
!
30
        }
!
31
32
        override func embeddableRoutingStep<A: ContainerAction>(with action: A) -> RoutingStep {
!
33
            return step.embeddableRoutingStep(with: action)
!
34
        }
!
35
36
    }
37
38
    /// Creates an instance of the `ActionToStepIntegrator` describing a container view controller.
39
    ///
40
    /// - Parameters:
41
    ///   - finder: The `UIViewController` `Finder`.
42
    ///   - factory: The `UIViewController` `ContainerFactory`.
43
    public init(finder: F, factory: FC) {
34x
44
        self.finder = finder
34x
45
        self.factory = factory
34x
46
    }
34x
47
48
    override func routingStep<A: Action>(with action: A) -> RoutingStep {
27x
49
        let entitiesCollector = BaseEntitiesCollector<ContainerFactoryBox<FC>, ActionBox>(finder: finder, factory: factory, action: action)
27x
50
        return BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
27x
51
    }
27x
52
53
    override func embeddableRoutingStep<A: ContainerAction>(with action: A) -> RoutingStep {
7x
54
        let entitiesCollector = BaseEntitiesCollector<ContainerFactoryBox<FC>, ContainerActionBox>(finder: finder, factory: factory, action: action)
7x
55
        return BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
7x
56
    }
7x
57
58
    /// Adapts context and view controller type dependencies.
59
    ///
60
    /// *NB:* Developer guaranties that this types will compliment in runtime.
61
    public func unsafelyRewrapped<VC: UIViewController, C>() -> ActionToStepIntegrator<VC, C> {
!
62
        return UnsafeWrapper(step: self)
!
63
    }
!
64
65
    /// Allows to avoid container view controller check.
66
    ///
67
    /// *NB:* Developer guaranties that it will be there in the runtime.
68
    public func expectingContainer<VC: ContainerViewController>() -> ActionToStepIntegrator<VC, F.Context> {
!
69
        return UnsafeWrapper(step: self)
!
70
    }
!
71
72
}
73
74
extension SingleContainerStep where FC.Context == Any? {
75
76
    /// Allows to avoid container view controller check. This method is available only for the steps that are
77
    /// able to accept any type of context.
78
    ///
79
    /// *NB:* Developer guaranties that it will be there in the runtime.
80
    public func expectingContainer<VC: ContainerViewController, C>() -> ActionToStepIntegrator<VC, C> {
!
81
        return UnsafeWrapper(step: self)
!
82
    }
!
83
84
    /// Allows to compliment to the type check. A step that has context equal to Optional(Any) can be build
85
    /// with any type of context passed to the router.
86
    public func adaptingContext<C>() -> ActionToStepIntegrator<F.ViewController, C> {
!
87
        return UnsafeWrapper(step: self)
!
88
    }
!
89
90
}
+
+ + + diff --git a/docs/tests/SingleNavigationRouter.swift.html b/docs/tests/SingleNavigationRouter.swift.html new file mode 100644 index 000000000..e538e75e1 --- /dev/null +++ b/docs/tests/SingleNavigationRouter.swift.html @@ -0,0 +1,457 @@ + + + +SingleNavigationRouter.swift - Slather + + + +
Slather logo
+

+Coverage for "SingleNavigationRouter.swift" : 71.79% +

+

(28 of 39 relevant lines covered)

+

RouteComposer/Classes/Extra/SingleNavigationRouter.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2019.
3
// Copyright © 2019 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
8
/// Lock object to be shared between `SingleNavigationRouter` instances.
9
public final class SingleNavigationLock {
10
11
    private var isNavigationInProgressFlag = false
12
13
    /// `SingleNavigationLock` state
14
    public var isNavigationInProgress: Bool {
5x
15
        return isNavigationInProgressFlag
5x
16
    }
5x
17
18
    /// Constructor
19
    public init() {
6x
20
    }
6x
21
22
    func startNavigation() {
2x
23
        isNavigationInProgressFlag = true
2x
24
    }
2x
25
26
    func stopNavigation() {
2x
27
        isNavigationInProgressFlag = false
2x
28
    }
2x
29
30
}
31
32
/// The `Router` proxy guarantees that not more than one navigation will happen simultaneously.
33
///
34
/// It is useful to avoid situations when the application can not control the amount of navigations
35
/// (for example, navigations triggered by push notifications)
36
public struct SingleNavigationRouter<R>: Router where R: Router {
37
38
    var router: R
39
40
    let lock: SingleNavigationLock
41
42
    /// Constructor
43
    ///
44
    /// - Parameters:
45
    ///   - router: `Router` instance to proxy.
46
    ///   - lock: Shared `SingleNavigationLock` instance.
47
    public init(router: R, lock: SingleNavigationLock) {
5x
48
        self.router = router
5x
49
        self.lock = lock
5x
50
    }
5x
51
52
    public func navigate<ViewController: UIViewController, Context>(to step: DestinationStep<ViewController, Context>,
53
                                                                    with context: Context,
54
                                                                    animated: Bool,
55
                                                                    completion: ((RoutingResult) -> Void)?) throws {
2x
56
        guard !lock.isNavigationInProgress else {
2x
57
            throw RoutingError.generic(RoutingError.Context("Navigation is in progress"))
1x
58
        }
1x
59
        lock.startNavigation()
1x
60
        do {
1x
61
            try router.navigate(to: step, with: context, animated: animated, completion: { success in
1x
62
                self.lock.stopNavigation()
1x
63
                completion?(success)
1x
64
            })
1x
65
        } catch let error {
1x
66
            lock.stopNavigation()
!
67
            throw error
!
68
        }
1x
69
    }
1x
70
71
}
72
73
extension SingleNavigationRouter: InterceptableRouter where R: InterceptableRouter {
74
75
    public mutating func add<RI: RoutingInterceptor>(_ interceptor: RI) where RI.Context == Any? {
!
76
        router.add(interceptor)
!
77
    }
!
78
79
    public mutating func add<CT: ContextTask>(_ contextTask: CT) where CT.ViewController == UIViewController, CT.Context == Any? {
!
80
        router.add(contextTask)
!
81
    }
!
82
83
    public mutating func add<PT: PostRoutingTask>(_ postTask: PT) where PT.Context == Any? {
!
84
        router.add(postTask)
!
85
    }
!
86
87
}
+
+ + + diff --git a/docs/tests/SingleStep.swift.html b/docs/tests/SingleStep.swift.html new file mode 100644 index 000000000..7122f9fb1 --- /dev/null +++ b/docs/tests/SingleStep.swift.html @@ -0,0 +1,472 @@ + + + +SingleStep.swift - Slather + + + +
Slather logo
+

+Coverage for "SingleStep.swift" : 70.59% +

+

(24 of 34 relevant lines covered)

+

RouteComposer/Classes/Steps/SingleStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 25/07/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// A simple class that produces an intermediate `ActionToStepIntegrator` describing any view controller.
9
public final class SingleStep<F: Finder, FC: Factory>: ActionToStepIntegrator<F.ViewController, F.Context>
10
        where
11
        F.ViewController == FC.ViewController, F.Context == FC.Context {
12
13
    let finder: F
14
15
    let factory: FC
16
17
    final class UnsafeWrapper<VC: UIViewController, C, F: Finder, FC: Factory>: ActionToStepIntegrator<VC, C>
18
            where
19
            F.ViewController == FC.ViewController, F.Context == FC.Context {
20
21
        let step: SingleStep<F, FC>
22
23
        init(step: SingleStep<F, FC>) {
9x
24
            self.step = step
9x
25
            super.init(taskCollector: step.taskCollector)
9x
26
        }
9x
27
28
        override func routingStep<A: Action>(with action: A) -> RoutingStep {
12x
29
            return step.routingStep(with: action)
12x
30
        }
12x
31
32
        override func embeddableRoutingStep<A: ContainerAction>(with action: A) -> RoutingStep {
!
33
            return step.embeddableRoutingStep(with: action)
!
34
        }
!
35
36
    }
37
38
    /// A simple class that produces an intermediate `ActionToStepIntegrator`.
39
    ///
40
    /// - Parameters:
41
    ///   - finder: The `UIViewController` `Finder`.
42
    ///   - factory: The `UIViewController` `Factory`.
43
    public init(finder: F, factory: FC) {
10x
44
        self.finder = finder
10x
45
        self.factory = factory
10x
46
    }
10x
47
48
    override func routingStep<A: Action>(with action: A) -> RoutingStep {
19x
49
        let entitiesCollector = BaseEntitiesCollector<FactoryBox<FC>, ActionBox>(finder: finder, factory: factory, action: action)
19x
50
        return BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
19x
51
    }
19x
52
53
    override func embeddableRoutingStep<A: ContainerAction>(with action: A) -> RoutingStep {
!
54
        let entitiesCollector = BaseEntitiesCollector<FactoryBox<FC>, ContainerActionBox>(finder: finder, factory: factory, action: action)
!
55
        return BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
!
56
    }
!
57
58
    /// Adapts context and view controller type dependencies.
59
    ///
60
    /// *NB:* Developer guaranties that this types will compliment in runtime.
61
    public func unsafelyRewrapped<VC: UIViewController, C>() -> ActionToStepIntegrator<VC, C> {
!
62
        return UnsafeWrapper(step: self)
!
63
    }
!
64
65
    /// Allows to avoid container view controller check.
66
    ///
67
    /// *NB:* Developer guaranties that it will be there in the runtime.
68
    public func expectingContainer<VC: ContainerViewController>() -> ActionToStepIntegrator<VC, F.Context> {
3x
69
        return UnsafeWrapper(step: self)
3x
70
    }
3x
71
72
}
73
74
extension SingleStep where FC.Context == Any? {
75
76
    /// Allows to avoid container view controller check. This method is available only for the steps that are
77
    /// able to accept any type of context.
78
    ///
79
    /// *NB:* Developer guaranties that it will be there in the runtime.
80
    public func expectingContainer<VC: ContainerViewController, C>() -> ActionToStepIntegrator<VC, C> {
4x
81
        return UnsafeWrapper(step: self)
4x
82
    }
4x
83
84
    /// Allows to compliment to the type check. A step that has context equal to Optional(Any) can be build
85
    /// with any type of context passed to the router.
86
    public func adaptingContext<C>() -> ActionToStepIntegrator<F.ViewController, C> {
2x
87
        return UnsafeWrapper(step: self)
2x
88
    }
2x
89
90
}
+
+ + + diff --git a/docs/tests/SplitControllerFactory.swift.html b/docs/tests/SplitControllerFactory.swift.html new file mode 100644 index 000000000..f6c8a3c73 --- /dev/null +++ b/docs/tests/SplitControllerFactory.swift.html @@ -0,0 +1,322 @@ + + + +SplitControllerFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "SplitControllerFactory.swift" : 81.48% +

+

(22 of 27 relevant lines covered)

+

RouteComposer/Classes/Factories/SplitControllerFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 16/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
///  The `ContainerFactory` that creates a `UISplitController` instance.
10
public struct SplitControllerFactory<C>: SimpleContainerFactory {
11
12
    /// `UISplitViewControllerDelegate` reference
13
    private(set) public weak var delegate: UISplitViewControllerDelegate?
14
15
    /// A property that controls how the primary view controller is hidden and displayed.
16
    /// A value of `.automatic` specifies the default behavior split view controller, which on an iPad,
17
    /// corresponds to an overlay mode in portrait and a side-by-side mode in landscape.
18
    public let preferredDisplayMode: UISplitViewController.DisplayMode?
19
20
    /// If 'true', hidden view can be presented and dismissed via a swipe gesture. Defaults to 'true'.
21
    public let presentsWithGesture: Bool?
22
23
    /// Block to configure `UISplitViewController`
24
    public let configuration: ((_: UISplitViewController) -> Void)?
25
26
    /// Constructor
27
    public init(delegate: UISplitViewControllerDelegate? = nil,
28
                presentsWithGesture: Bool? = nil,
29
                isCollapsed: Bool? = nil,
30
                preferredDisplayMode: UISplitViewController.DisplayMode? = nil,
31
                configuration: ((_: UISplitViewController) -> Void)? = nil) {
1x
32
        self.delegate = delegate
1x
33
        self.preferredDisplayMode = preferredDisplayMode
1x
34
        self.presentsWithGesture = presentsWithGesture
1x
35
        self.configuration = configuration
1x
36
    }
1x
37
38
    public func build(with context: C, integrating viewControllers: [UIViewController]) throws -> UISplitViewController {
1x
39
        guard !viewControllers.isEmpty else {
1x
40
            throw RoutingError.compositionFailed(.init("No master or derails view controllers provided."))
!
41
        }
1x
42
1x
43
        let splitController = UISplitViewController(nibName: nil, bundle: nil)
1x
44
        if let presentsWithGesture = presentsWithGesture {
1x
45
            splitController.presentsWithGesture = presentsWithGesture
!
46
        }
1x
47
        if let preferredDisplayMode = preferredDisplayMode {
1x
48
            splitController.preferredDisplayMode = preferredDisplayMode
!
49
        }
1x
50
        if let delegate = delegate {
1x
51
            splitController.delegate = delegate
!
52
        }
1x
53
        if let configuration = configuration {
1x
54
            configuration(splitController)
!
55
        }
1x
56
        splitController.viewControllers = viewControllers
1x
57
        return splitController
1x
58
    }
1x
59
60
}
+
+ + + diff --git a/docs/tests/SplitControllerStep.swift.html b/docs/tests/SplitControllerStep.swift.html new file mode 100644 index 000000000..112f916e5 --- /dev/null +++ b/docs/tests/SplitControllerStep.swift.html @@ -0,0 +1,102 @@ + + + +SplitControllerStep.swift - Slather + + + +
Slather logo
+

+Coverage for "SplitControllerStep.swift" : 0.00% +

+

(0 of 3 relevant lines covered)

+

RouteComposer/Classes/Steps/SplitControllerStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// Default split container step
9
public final class SplitControllerStep<Context>: SingleContainerStep<NilFinder<UISplitViewController, Context>, SplitControllerFactory<Context>> {
10
11
    /// Constructor.
12
    public init() {
!
13
        super.init(finder: NilFinder(), factory: SplitControllerFactory())
!
14
    }
!
15
16
}
+
+ + + diff --git a/docs/tests/SplitViewController+Extension.swift.html b/docs/tests/SplitViewController+Extension.swift.html new file mode 100644 index 000000000..35b4adcfa --- /dev/null +++ b/docs/tests/SplitViewController+Extension.swift.html @@ -0,0 +1,357 @@ + + + +SplitViewController+Extension.swift - Slather + + + +
Slather logo
+

+Coverage for "SplitViewController+Extension.swift" : 58.06% +

+

(18 of 31 relevant lines covered)

+

RouteComposer/Classes/Extensions/SplitViewController+Extension.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 16/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
// - The `UISplitViewController` extension is to support the `ContainerViewController` protocol
10
extension UISplitViewController: ContainerViewController {
11
12
    public var containedViewControllers: [UIViewController] {
58x
13
        return viewControllers
58x
14
    }
58x
15
16
    public var visibleViewControllers: [UIViewController] {
33x
17
        return containedViewControllers
33x
18
    }
33x
19
20
    // ###NB
21
    // `UISplitViewController` does not support showing primary view controller overlay programmatically out of the box in .primaryOverlay
22
    // mode, so `makeVisible` wont be able to serve it.
23
    //
24
    // However, it can serve some edge cases when `UISplitViewController` is collapsed and primary view controller is `UINavigationController`.
25
    public func makeVisible(_ viewController: UIViewController, animated: Bool) {
7x
26
        guard UIViewController.findViewController(in: self, options: [.contained], using: { $0 === viewController }) != nil else {
7x
27
            return
!
28
        }
7x
29
        if isCollapsed {
7x
30
            guard viewController.navigationController?.visibleViewController != viewController else {
3x
31
                return
!
32
            }
3x
33
            viewController.navigationController?.popToViewController(viewController, animated: animated)
3x
34
        }
7x
35
    }
7x
36
37
    // Replacing of the child view controllers is not fully supported by the implementation of `UISplitViewController`.
38
    // Only some common cases are covered by this method.
39
    //
40
    // ###NB
41
    // Please read: https://developer.apple.com/documentation/uikit/uisplitviewcontroller
42
    //
43
    // Quote:
44
    // When designing your split view interface, it is best to install primary and secondary view controllers that do not change.
45
    // A common technique is to install navigation controllers in both positions and then push and pop new content as needed.
46
    public func replace(containedViewControllers: [UIViewController], animated: Bool, completion: @escaping () -> Void) {
!
47
        if containedViewControllers.count > 1,
!
48
           let primaryViewController = self.containedViewControllers.first,
!
49
           primaryViewController === containedViewControllers.first,
!
50
           let detailsViewController = containedViewControllers.last {
!
51
            showDetailViewController(detailsViewController, sender: self)
!
52
        } else {
!
53
            viewControllers = containedViewControllers
!
54
        }
!
55
        completion()
!
56
    }
!
57
58
}
59
60
// - The `UISplitViewController` extension is to support the `RoutingInterceptable` protocol
61
extension UISplitViewController: RoutingInterceptable {
62
63
    public var canBeDismissed: Bool {
6x
64
        return containedViewControllers.canBeDismissed
6x
65
    }
6x
66
67
}
+
+ + + diff --git a/docs/tests/StackIteratingFinder.swift.html b/docs/tests/StackIteratingFinder.swift.html new file mode 100644 index 000000000..0295d7648 --- /dev/null +++ b/docs/tests/StackIteratingFinder.swift.html @@ -0,0 +1,247 @@ + + + +StackIteratingFinder.swift - Slather + + + +
Slather logo
+

+Coverage for "StackIteratingFinder.swift" : 100.00% +

+

(10 of 10 relevant lines covered)

+

RouteComposer/Classes/Finders/StackIteratingFinder.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// `StackIteratingFinder` iterates through the view controllers stack
10
/// following the search options provided. It simplifies the creation of the finders for a hosting app.
11
public protocol StackIteratingFinder: Finder {
12
13
    /// Type of `UIViewController` that `StackIteratingFinder` can find
14
    associatedtype ViewController
15
16
    /// Type of `Context` object that `StackIteratingFinder` can deal with
17
    associatedtype Context
18
19
    /// `StackIterator` to be used by `StackIteratingFinder`
20
    var iterator: StackIterator { get }
21
22
    /// The method to be implemented by the `StackIteratingFinder` instance
23
    ///
24
    /// - Parameters:
25
    ///   - viewController: A view controller in the current view controller stack
26
    ///   - context: The `Context` instance provided to the `Router`.
27
    /// - Returns: true if this view controller is the one that `Finder` is looking for, false otherwise.
28
    func isTarget(_ viewController: ViewController, with context: Context) -> Bool
29
30
}
31
32
public extension StackIteratingFinder {
33
34
    func findViewController(with context: Context) -> ViewController? {
149x
35
        let predicate: (UIViewController) -> Bool = {
599x
36
            guard let viewController = $0 as? ViewController else {
599x
37
                return false
532x
38
            }
532x
39
            return self.isTarget(viewController, with: context)
67x
40
        }
599x
41
149x
42
        return iterator.firstViewController(where: predicate) as? ViewController
149x
43
    }
149x
44
45
}
+
+ + + diff --git a/docs/tests/StepAssembly.swift.html b/docs/tests/StepAssembly.swift.html new file mode 100644 index 000000000..1f0cbfe19 --- /dev/null +++ b/docs/tests/StepAssembly.swift.html @@ -0,0 +1,477 @@ + + + +StepAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "StepAssembly.swift" : 100.00% +

+

(34 of 34 relevant lines covered)

+

RouteComposer/Classes/Assemblies/StepAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 05/02/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Builds a `DestinationStep` instance with the correct settings into a chain of steps.
9
/// ### NB
10
/// Both `Finder` and `Factory` instances should deal with the same type of `UIViewController` and `Context` instances.
11
/// ### Usage
12
/// ```swift
13
/// let productScreen = StepAssembly(finder: ProductViewControllerFinder(), factory: ProductViewControllerFactory())
14
///         .adding(LoginInterceptor())
15
///         .adding(ProductViewControllerContextTask())
16
///         .adding(ProductViewControllerPostTask(analyticsManager: AnalyticsManager.sharedInstance))
17
///         .using(UINavigationController.push())
18
///         .from(NavigationControllerStep())
19
///         .using(GeneralAction.presentModally())
20
///         .from(GeneralStep.current())
21
///         .assemble()
22
/// ```
23
public final class StepAssembly<F: Finder, FC: Factory>: GenericStepAssembly<F.ViewController, FC.Context>, ActionConnecting
24
        where
25
        F.ViewController == FC.ViewController, F.Context == FC.Context {
26
27
    let finder: F
28
29
    let factory: FC
30
31
    let previousSteps: [RoutingStep]
32
33
    /// Constructor
34
    ///
35
    /// - Parameters:
36
    ///   - finder: The `UIViewController` `Finder` instance.
37
    ///   - factory: The `UIViewController` `Factory` instance.
38
    public init(finder: F, factory: FC) {
145x
39
        self.factory = factory
145x
40
        self.finder = finder
145x
41
        self.previousSteps = []
145x
42
    }
145x
43
44
    public func using<A: Action>(_ action: A) -> StepChainAssembly<ViewController, Context> {
55x
45
        var previousSteps = self.previousSteps
55x
46
        let entitiesCollector = BaseEntitiesCollector<FactoryBox<FC>, ActionBox>(finder: finder, factory: factory, action: action)
55x
47
        let step = BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
55x
48
        previousSteps.append(step)
55x
49
        return StepChainAssembly(previousSteps: previousSteps)
55x
50
    }
55x
51
52
    public func using<A: ContainerAction>(_ action: A) -> ContainerStepChainAssembly<A.ViewController, ViewController, Context> {
49x
53
        var previousSteps = self.previousSteps
49x
54
        let entitiesCollector = BaseEntitiesCollector<FactoryBox<FC>, ContainerActionBox>(finder: finder, factory: factory, action: action)
49x
55
        let step = BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
49x
56
        previousSteps.append(step)
49x
57
        return ContainerStepChainAssembly(previousSteps: previousSteps)
49x
58
    }
49x
59
60
}
61
62
public extension StepAssembly where FC: NilEntity {
63
64
    /// Connects previously provided `ActionToStepIntegrator` with `NilEntity` factory with a step where the `UIViewController`
65
    /// should avoid type checks
66
    /// Example: `UIViewController` instance was loaded as a part of the stack inside of the storyboard.
67
    ///
68
    /// - Parameter step: `ActionToStepIntegrator` instance to be used.
69
    func from<VC: UIViewController>(_ step: ActionToStepIntegrator<VC, Context>) -> ActionConnectingAssembly<VC, ViewController, Context> {
7x
70
        var previousSteps = self.previousSteps
7x
71
        let entitiesCollector = BaseEntitiesCollector<FactoryBox<FC>, ActionBox>(finder: finder, factory: factory, action: ViewControllerActions.NilAction())
7x
72
        let currentStep = BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
7x
73
        previousSteps.append(currentStep)
7x
74
        return ActionConnectingAssembly(stepToFullFill: step, previousSteps: previousSteps)
7x
75
    }
7x
76
77
    /// Connects previously provided `DestinationStep` with `NilEntity` factory with a step where the `UIViewController`
78
    /// should avoid type checks
79
    /// Example: `UIViewController` instance was loaded as a part of the stack inside of the storyboard.
80
    ///
81
    /// - Parameter step: `DestinationStep` instance to be used.
82
    func from<VC: UIViewController>(_ step: DestinationStep<VC, Context>) -> LastStepInChainAssembly<ViewController, Context> {
34x
83
        var previousSteps = self.previousSteps
34x
84
        let entitiesCollector = BaseEntitiesCollector<FactoryBox<FC>, ActionBox>(finder: finder, factory: factory, action: ViewControllerActions.NilAction())
34x
85
        let currentStep = BaseStep(entitiesProvider: entitiesCollector, taskProvider: taskCollector)
34x
86
        previousSteps.append(currentStep)
34x
87
        previousSteps.append(step)
34x
88
        return LastStepInChainAssembly(previousSteps: previousSteps)
34x
89
    }
34x
90
91
}
+
+ + + diff --git a/docs/tests/StepChainAssembly.swift.html b/docs/tests/StepChainAssembly.swift.html new file mode 100644 index 000000000..6cb597e3b --- /dev/null +++ b/docs/tests/StepChainAssembly.swift.html @@ -0,0 +1,237 @@ + + + +StepChainAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "StepChainAssembly.swift" : 81.25% +

+

(13 of 16 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/StepChainAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 11/09/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Helper class to build a chain of steps. Can not be used directly.
9
public struct StepChainAssembly<ViewController: UIViewController, Context> {
10
11
    let previousSteps: [RoutingStep]
12
13
    init(previousSteps: [RoutingStep]) {
90x
14
        self.previousSteps = previousSteps
90x
15
    }
90x
16
17
    /// Adds a single step to the chain
18
    ///
19
    /// - Parameter previousStep: The instance of `StepWithActionAssemblable`
20
    public func from<VC: UIViewController>(_ step: ActionToStepIntegrator<VC, Context>) -> ActionConnectingAssembly<VC, ViewController, Context> {
!
21
        return ActionConnectingAssembly<VC, ViewController, Context>(stepToFullFill: step, previousSteps: previousSteps)
!
22
    }
!
23
24
    /// Adds a `DestinationStep` to the chain. This step will be the last one in the chain.
25
    ///
26
    /// - Parameter previousStep: The instance of `DestinationStep`
27
    public func from<VC: UIViewController>(_ step: DestinationStep<VC, Context>) -> LastStepInChainAssembly<ViewController, Context> {
86x
28
        var previousSteps = self.previousSteps
86x
29
        previousSteps.append(step)
86x
30
        return LastStepInChainAssembly<ViewController, Context>(previousSteps: previousSteps)
86x
31
    }
86x
32
33
    /// Assembles all the provided settings.
34
    ///
35
    /// - Parameter step: An instance of `DestinationStep` to start to build a current step from.
36
    /// - Returns: An instance of `DestinationStep` with all the provided settings inside.
37
    public func assemble<VC: UIViewController>(from step: DestinationStep<VC, Context>) -> DestinationStep<ViewController, Context> {
4x
38
        var previousSteps = self.previousSteps
4x
39
        previousSteps.append(step)
4x
40
        return LastStepInChainAssembly<ViewController, Context>(previousSteps: previousSteps).assemble()
4x
41
    }
4x
42
43
}
+
+ + + diff --git a/docs/tests/StoryboardFactory.swift.html b/docs/tests/StoryboardFactory.swift.html new file mode 100644 index 000000000..10528e0eb --- /dev/null +++ b/docs/tests/StoryboardFactory.swift.html @@ -0,0 +1,312 @@ + + + +StoryboardFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "StoryboardFactory.swift" : 71.43% +

+

(20 of 28 relevant lines covered)

+

RouteComposer/Classes/Factories/StoryboardFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// The `Factory` that creates a `UIViewController` from a storyboard.
9
public struct StoryboardFactory<VC: UIViewController, C>: Factory {
10
11
    /// The name of a storyboard file
12
    public let storyboardName: String
13
14
    /// The `Bundle` instance
15
    public let bundle: Bundle?
16
17
    /// The `UIViewController` identifier in the storyboard. If it is not set, the `Factory` will try
18
    /// to create the storyboards initial `UIViewController`
19
    public let viewControllerID: String?
20
21
    /// Constructor
22
    ///
23
    /// - Parameters:
24
    ///   - storyboardName: The name of a storyboard file
25
    ///   - bundle: The `Bundle` instance if needed
26
    ///   - viewControllerID: The `UIViewController` identifier in the storyboard. If it is not set, the `Factory` will try
27
    ///     to create the storyboards initial `UIViewController`
28
    public init(storyboardName: String, bundle: Bundle? = nil, viewControllerID: String? = nil) {
78x
29
        self.storyboardName = storyboardName
78x
30
        self.bundle = bundle
78x
31
        self.viewControllerID = viewControllerID
78x
32
    }
78x
33
34
    public func build(with context: C) throws -> VC {
46x
35
        let storyboard = UIStoryboard(name: storyboardName, bundle: bundle)
46x
36
        if let viewControllerID = viewControllerID {
46x
37
            let instantiatedViewController = storyboard.instantiateViewController(withIdentifier: viewControllerID)
21x
38
            guard let viewController = instantiatedViewController as? VC else {
21x
39
                throw RoutingError.compositionFailed(.init("Unable to instantiate UIViewController with " +
!
40
                        " \(viewControllerID) identifier in \(storyboardName) storyboard"))
!
41
            }
21x
42
            return viewController
21x
43
        } else {
25x
44
            guard let abstractViewController = storyboard.instantiateInitialViewController() else {
25x
45
                throw RoutingError.compositionFailed(.init("Unable to instantiate initial UIViewController " +
!
46
                        "in \(storyboardName) storyboard"))
!
47
            }
25x
48
            guard let viewController = abstractViewController as? ViewController else {
25x
49
                throw RoutingError.typeMismatch(type(of: abstractViewController), .init("Unable to instantiate the initial " +
!
50
                        "UIViewController in \(storyboardName) storyboard as \(String(describing: type(of: ViewController.self))), " +
!
51
                        "got \(String(describing: abstractViewController)) instead."))
!
52
            }
25x
53
25x
54
            return viewController
25x
55
        }
25x
56
    }
!
57
58
}
+
+ + + diff --git a/docs/tests/SwitchAssembly.swift.html b/docs/tests/SwitchAssembly.swift.html new file mode 100644 index 000000000..2315e0a48 --- /dev/null +++ b/docs/tests/SwitchAssembly.swift.html @@ -0,0 +1,737 @@ + + + +SwitchAssembly.swift - Slather + + + +
Slather logo
+

+Coverage for "SwitchAssembly.swift" : 91.49% +

+

(43 of 47 relevant lines covered)

+

RouteComposer/Classes/Assemblies/SwitchAssembly.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 14/02/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Builds a `DestinationStep` which can contain the conditions to select the steps to be taken by a `Router`.
9
/// ### Usage
10
/// ```swift
11
///        let containerScreen = SwitchAssembly<UINavigationController, ProductContext>()
12
///                .addCase { (context: ProductContext) in
13
///                    // If this configuration is requested by a Universal Link (productURL != nil), then present modally.
14
///                    guard context.productURL != nil else {
15
///                        return nil
16
///                    }
17
///
18
///                    return ChainAssembly.from(NavigationControllerStep<ProductContext>())
19
///                            .using(GeneralAction.presentModally())
20
///                            .from(GeneralStep.current())
21
///                            .assemble()
22
///
23
///                }
24
///
25
///                // If UINavigationController is visible on the screen - just push
26
///                .addCase(from: ClassFinder<UINavigationController, ProductContext>(options: .currentVisibleOnly))
27
///
28
///                // Otherwise - present modally
29
///                .assemble(default: {
30
///                    return ChainAssembly.from(NavigationControllerStep<ProductContext>())
31
///                            .using(GeneralAction.presentModally())
32
///                            .from(GeneralStep.current())
33
///                            .assemble()
34
///                })
35
/// ```
36
public final class SwitchAssembly<ViewController: UIViewController, Context> {
37
38
    private struct BlockResolver<C>: StepCaseResolver {
39
40
        let resolverBlock: ((_: C) -> DestinationStep<ViewController, Context>?)
41
42
        init(resolverBlock: @escaping ((_: C) -> DestinationStep<ViewController, Context>?)) {
8x
43
            self.resolverBlock = resolverBlock
8x
44
        }
8x
45
46
        func resolve(with context: Any?) -> RoutingStep? {
7x
47
            guard let typedDestination = context as? C else {
7x
48
                return nil
!
49
            }
7x
50
            return resolverBlock(typedDestination)
7x
51
        }
7x
52
    }
53
54
    private struct FinderResolver<ViewController: UIViewController, Context>: StepCaseResolver {
55
56
        private let finder: AnyFinder?
57
58
        private let step: DestinationStep<ViewController, Context>
59
60
        init<F: Finder>(finder: F, step: DestinationStep<ViewController, Context>?) {
6x
61
            self.step = step ?? DestinationStep(GeneralStep.FinderStep(finder: finder))
6x
62
            self.finder = FinderBox(finder)
6x
63
        }
6x
64
65
        func resolve<C>(with context: C) -> RoutingStep? {
5x
66
            guard (try? finder?.findViewController(with: context)) != nil else {
5x
67
                return nil
2x
68
            }
3x
69
            return step
3x
70
        }
5x
71
    }
72
73
    private var resolvers: [StepCaseResolver] = []
74
75
    /// Constructor
76
    public init() {
4x
77
4x
78
    }
4x
79
80
    /// Adds a block that allows a written decision case for the `Router` in the block.
81
    /// Returning nil from the block will mean that it has not succeeded.
82
    ///
83
    /// - Parameter resolverBlock: case resolver block
84
    public func addCase<C>(_ resolverBlock: @escaping ((_: C) -> DestinationStep<ViewController, Context>?)) -> Self {
4x
85
        resolvers.append(BlockResolver(resolverBlock: resolverBlock))
4x
86
        return self
4x
87
    }
4x
88
89
    /// Adds a case when a view controller exists in the stack in order to make a particular `DestinationStep`.
90
    ///
91
    /// - Parameters:
92
    ///   - finder: The `Finder` instance searches for a `UIViewController` in the stack
93
    ///   - step: The `DestinationStep` is to perform if the `Finder` has been able to find a view controller in the stack. If not provided,
94
    ///   a `UIViewController` found by the `Finder` will be considered as a view controller to start the navigation process from
95
    public func addCase<F: Finder>(when finder: F, from step: DestinationStep<ViewController, Context>) -> Self {
1x
96
        resolvers.append(FinderResolver(finder: finder, step: step))
1x
97
        return self
1x
98
    }
1x
99
100
    /// Adds a case when a view controller exists - navigation will start from the resulting view controller.
101
    ///
102
    /// - Parameters:
103
    ///   - finder: The `Finder` instance is to find a `UIViewController` in the stack
104
    ///   a `UIViewController` found by the `Finder` will be considered as a view controller to start the navigation process from
105
    public func addCase<F: Finder>(from finder: F) -> Self where F.ViewController == ViewController, F.Context == Context {
4x
106
        resolvers.append(FinderResolver<ViewController, Context>(finder: finder, step: nil))
4x
107
        return self
4x
108
    }
4x
109
110
    /// Assembles all the cases into a `DestinationStep` implementation
111
    ///
112
    /// - Returns: instance of a `DestinationStep`
113
    public func assemble() -> DestinationStep<ViewController, Context> {
!
114
        return DestinationStep(SwitcherStep(resolvers: resolvers))
!
115
    }
!
116
117
    /// Assembles all the cases in a `DestinationStep` instance and adds the default implementation, providing the step it is to perform
118
    ///
119
    /// - Parameter resolverBlock: default resolver block
120
    /// - Returns: an instance of `DestinationStep`
121
    public func assemble(default resolverBlock: @escaping (() -> DestinationStep<ViewController, Context>)) -> DestinationStep<ViewController, Context> {
4x
122
        resolvers.append(BlockResolver<Context>(resolverBlock: { _ in
4x
123
            return resolverBlock()
2x
124
        }))
2x
125
        return DestinationStep(SwitcherStep(resolvers: resolvers))
4x
126
    }
4x
127
128
}
129
130
extension SwitchAssembly where ViewController: ContainerViewController {
131
132
    /// Adds a case when a view controller exists - navigation will start from the resulting view controller.
133
    /// This method allows to avoid view controller type check.
134
    ///
135
    /// - Parameters:
136
    ///   - finder: The `Finder` instance is to find a `UIViewController` in the stack
137
    ///   a `UIViewController` found by the `Finder` will be considered as a view controller to start the navigation process from
138
    public func addCase<F: Finder>(expecting finder: F) -> Self where F.Context == Context {
1x
139
        resolvers.append(FinderResolver<ViewController, Context>(finder: finder, step: nil))
1x
140
        return self
1x
141
    }
1x
142
143
}
+
+ + + diff --git a/docs/tests/SwitcherStep.swift.html b/docs/tests/SwitcherStep.swift.html new file mode 100644 index 000000000..73bbafe6a --- /dev/null +++ b/docs/tests/SwitcherStep.swift.html @@ -0,0 +1,177 @@ + + + +SwitcherStep.swift - Slather + + + +
Slather logo
+

+Coverage for "SwitcherStep.swift" : 100.00% +

+

(11 of 11 relevant lines covered)

+

RouteComposer/Classes/Router/Internal/SwitcherStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 05/02/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
protocol StepCaseResolver {
9
10
    func resolve(with context: Any?) -> RoutingStep?
11
12
}
13
14
class SwitcherStep: RoutingStep, ChainableStep {
15
16
    var resolvers: [StepCaseResolver]
17
18
    func getPreviousStep(with context: Any?) -> RoutingStep? {
5x
19
        return resolvers.reduce(nil as RoutingStep?, { (result, resolver) in
15x
20
            guard result == nil else {
15x
21
                return result
3x
22
            }
12x
23
            return resolver.resolve(with: context)
12x
24
        })
15x
25
    }
5x
26
27
    init(resolvers: [StepCaseResolver]) {
4x
28
        self.resolvers = resolvers
4x
29
    }
4x
30
31
}
+
+ + + diff --git a/docs/tests/TabBarControllerFactory.swift.html b/docs/tests/TabBarControllerFactory.swift.html new file mode 100644 index 000000000..089de8b63 --- /dev/null +++ b/docs/tests/TabBarControllerFactory.swift.html @@ -0,0 +1,222 @@ + + + +TabBarControllerFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "TabBarControllerFactory.swift" : 78.95% +

+

(15 of 19 relevant lines covered)

+

RouteComposer/Classes/Factories/TabBarControllerFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 07/02/2018.
3
//
4
5
import Foundation
6
import UIKit
7
8
///  The `ContainerFactory` that creates a `UITabBarController` instance.
9
public struct TabBarControllerFactory<C>: SimpleContainerFactory {
10
11
    /// `UITabBarControllerDelegate` reference
12
    private(set) public weak var delegate: UITabBarControllerDelegate?
13
14
    /// Block to configure `UITabBarController`
15
    public let configuration: ((_: UITabBarController) -> Void)?
16
17
    /// Constructor
18
    public init(delegate: UITabBarControllerDelegate? = nil,
19
                configuration: ((_: UITabBarController) -> Void)? = nil) {
16x
20
        self.delegate = delegate
16x
21
        self.configuration = configuration
16x
22
    }
16x
23
24
    public func build(with context: C, integrating viewControllers: [UIViewController]) throws -> UITabBarController {
12x
25
        guard !viewControllers.isEmpty else {
12x
26
            throw RoutingError.compositionFailed(.init("Unable to build UITabBarController due " +
!
27
                    "to 0 amount of the children view controllers"))
!
28
        }
12x
29
        let tabBarController = UITabBarController()
12x
30
        if let delegate = delegate {
12x
31
            tabBarController.delegate = delegate
!
32
        }
12x
33
        if let configuration = configuration {
12x
34
            configuration(tabBarController)
!
35
        }
12x
36
        tabBarController.viewControllers = viewControllers
12x
37
        return tabBarController
12x
38
    }
12x
39
40
}
+
+ + + diff --git a/docs/tests/TabBarControllerStep.swift.html b/docs/tests/TabBarControllerStep.swift.html new file mode 100644 index 000000000..eedf02a19 --- /dev/null +++ b/docs/tests/TabBarControllerStep.swift.html @@ -0,0 +1,102 @@ + + + +TabBarControllerStep.swift - Slather + + + +
Slather logo
+

+Coverage for "TabBarControllerStep.swift" : 100.00% +

+

(3 of 3 relevant lines covered)

+

RouteComposer/Classes/Steps/TabBarControllerStep.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 15/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import UIKit
7
8
/// Default tab bar container step
9
public final class TabBarControllerStep<Context>: SingleContainerStep<NilFinder<UITabBarController, Context>, TabBarControllerFactory<Context>> {
10
11
    /// Constructor
12
    public init() {
8x
13
        super.init(finder: NilFinder(), factory: TabBarControllerFactory())
8x
14
    }
8x
15
16
}
+
+ + + diff --git a/docs/tests/TabBarViewController+Extension.swift.html b/docs/tests/TabBarViewController+Extension.swift.html new file mode 100644 index 000000000..ca0ef82d3 --- /dev/null +++ b/docs/tests/TabBarViewController+Extension.swift.html @@ -0,0 +1,262 @@ + + + +TabBarViewController+Extension.swift - Slather + + + +
Slather logo
+

+Coverage for "TabBarViewController+Extension.swift" : 76.92% +

+

(20 of 26 relevant lines covered)

+

RouteComposer/Classes/Extensions/TabBarViewController+Extension.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 16/01/2018.
3
// Copyright © 2018 HBC Digital. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// - The `UITabBarController` extension is to support the `ContainerViewController` protocol
10
extension UITabBarController: ContainerViewController {
11
12
    public var containedViewControllers: [UIViewController] {
211x
13
        guard let viewControllers = self.viewControllers else {
211x
14
            return []
!
15
        }
211x
16
        return viewControllers
211x
17
    }
211x
18
19
    public var visibleViewControllers: [UIViewController] {
235x
20
        guard let visibleViewController = selectedViewController else {
235x
21
            return []
!
22
        }
235x
23
        return [visibleViewController]
235x
24
    }
235x
25
26
    public func makeVisible(_ viewController: UIViewController, animated: Bool) {
40x
27
        guard selectedViewController != viewController,
40x
28
              let viewControllerToSelect = containedViewControllers.first(where: { $0 == viewController }) else {
43x
29
            return
17x
30
        }
23x
31
        self.selectedViewController = viewControllerToSelect
23x
32
    }
23x
33
34
    public func replace(containedViewControllers: [UIViewController], animated: Bool, completion: @escaping () -> Void) {
!
35
        setViewControllers(containedViewControllers, animated: animated)
!
36
        completion()
!
37
    }
!
38
39
}
40
41
/// - The `UITabBarController` extension is to support the `RoutingInterceptable` protocol
42
extension UITabBarController: RoutingInterceptable {
43
44
    public var canBeDismissed: Bool {
69x
45
        return containedViewControllers.canBeDismissed
69x
46
    }
69x
47
48
}
+
+ + + diff --git a/docs/tests/TaskCollector.swift.html b/docs/tests/TaskCollector.swift.html new file mode 100644 index 000000000..cceb4c598 --- /dev/null +++ b/docs/tests/TaskCollector.swift.html @@ -0,0 +1,217 @@ + + + +TaskCollector.swift - Slather + + + +
Slather logo
+

+Coverage for "TaskCollector.swift" : 100.00% +

+

(18 of 18 relevant lines covered)

+

RouteComposer/Classes/Assemblies/Helpers/TaskCollector.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 31/08/2018.
3
//
4
5
import Foundation
6
7
struct TaskCollector: TaskProvider {
8
9
    private var interceptors: [AnyRoutingInterceptor] = []
10
11
    private var contextTasks: [AnyContextTask] = []
12
13
    private var postTasks: [AnyPostRoutingTask] = []
14
15
    mutating func add<RI: RoutingInterceptor>(_ interceptor: RI) {
18x
16
        self.interceptors.append(RoutingInterceptorBox(interceptor))
18x
17
    }
18x
18
19
    mutating func add<CT: ContextTask>(_ contextTask: CT) {
90x
20
        self.contextTasks.append(ContextTaskBox(contextTask))
90x
21
    }
90x
22
23
    mutating func add<PT: PostRoutingTask>(_ postTask: PT) {
7x
24
        self.postTasks.append(PostRoutingTaskBox(postTask))
7x
25
    }
7x
26
27
    var interceptor: AnyRoutingInterceptor? {
202x
28
        return !interceptors.isEmpty ? interceptors.count == 1 ? interceptors.first : InterceptorMultiplexer(interceptors) : nil
202x
29
    }
202x
30
31
    var contextTask: AnyContextTask? {
202x
32
        return !contextTasks.isEmpty ? contextTasks.count == 1 ? contextTasks.first : ContextTaskMultiplexer(contextTasks) : nil
202x
33
    }
202x
34
35
    var postTask: AnyPostRoutingTask? {
202x
36
        return !postTasks.isEmpty ? postTasks.count == 1 ? postTasks.first : PostRoutingTaskMultiplexer(postTasks) : nil
202x
37
    }
202x
38
39
}
+
+ + + diff --git a/docs/tests/UINavigationController+Action.swift.html b/docs/tests/UINavigationController+Action.swift.html new file mode 100644 index 000000000..b5232fbb0 --- /dev/null +++ b/docs/tests/UINavigationController+Action.swift.html @@ -0,0 +1,512 @@ + + + +UINavigationController+Action.swift - Slather + + + +
Slather logo
+

+Coverage for "UINavigationController+Action.swift" : 84.62% +

+

(33 of 39 relevant lines covered)

+

RouteComposer/Classes/Actions/UINavigationController+Action.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-09-18.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Actions for `UINavigationController`
9
public extension ContainerViewController where Self: UINavigationController {
10
11
    /// Replaces all the child view controllers in the `UINavigationController`'s children stack
12
    static func pushAsRoot() -> NavigationControllerActions.PushAsRootAction<Self> {
3x
13
        return NavigationControllerActions.PushAsRootAction()
3x
14
    }
3x
15
16
    /// Pushes a child view controller into the `UINavigationController`'s children stack
17
    static func push() -> NavigationControllerActions.PushAction<Self> {
58x
18
        return NavigationControllerActions.PushAction()
58x
19
    }
58x
20
21
    /// Pushes a child view controller, replacing the existing, into the `UINavigationController`'s children stack
22
    static func pushReplacingLast() -> NavigationControllerActions.PushReplacingLastAction<Self> {
3x
23
        return NavigationControllerActions.PushReplacingLastAction()
3x
24
    }
3x
25
26
}
27
28
/// Actions for `UINavigationController`
29
public struct NavigationControllerActions {
30
31
    /// Pushes a view controller into `UINavigationController`'s child stack
32
    public struct PushAction<ViewController: UINavigationController>: ContainerAction {
33
34
        /// Constructor
35
        init() {
58x
36
        }
58x
37
38
        public func perform(with viewController: UIViewController,
39
                            on navigationController: ViewController,
40
                            animated: Bool,
41
                            completion: @escaping(_: ActionResult) -> Void) {
10x
42
            navigationController.pushViewController(viewController, animated: animated)
10x
43
            return completion(.continueRouting)
10x
44
        }
10x
45
46
    }
47
48
    /// Replaces all the child view controllers in the `UINavigationController`'s child stack
49
    public struct PushAsRootAction<ViewController: UINavigationController>: ContainerAction {
50
51
        /// Constructor
52
        init() {
3x
53
        }
3x
54
55
        public func perform(embedding viewController: UIViewController,
56
                            in childViewControllers: inout [UIViewController]) {
2x
57
            childViewControllers.removeAll()
2x
58
            childViewControllers.append(viewController)
2x
59
        }
2x
60
61
        public func perform(with viewController: UIViewController,
62
                            on navigationController: ViewController,
63
                            animated: Bool,
64
                            completion: @escaping(_: ActionResult) -> Void) {
1x
65
            navigationController.setViewControllers([viewController], animated: animated)
1x
66
            return completion(.continueRouting)
1x
67
        }
1x
68
69
    }
70
71
    /// Pushes a view controller into the `UINavigationController`'s child stack replacing the last one
72
    public struct PushReplacingLastAction<ViewController: UINavigationController>: ContainerAction {
73
74
        /// Constructor
75
        init() {
3x
76
        }
3x
77
78
        public func perform(embedding viewController: UIViewController,
79
                            in childViewControllers: inout [UIViewController]) {
3x
80
            if !childViewControllers.isEmpty {
3x
81
                childViewControllers.removeLast()
2x
82
            }
3x
83
            childViewControllers.append(viewController)
3x
84
        }
3x
85
86
        public func perform(with viewController: UIViewController,
87
                            on navigationController: ViewController,
88
                            animated: Bool,
89
                            completion: @escaping(_: ActionResult) -> Void) {
!
90
            var viewControllers = navigationController.viewControllers
!
91
            perform(embedding: viewController, in: &viewControllers)
!
92
            navigationController.setViewControllers(viewControllers, animated: animated)
!
93
            return completion(.continueRouting)
!
94
        }
!
95
96
    }
97
98
}
+
+ + + diff --git a/docs/tests/UISplitViewController+Action.swift.html b/docs/tests/UISplitViewController+Action.swift.html new file mode 100644 index 000000000..fc5f3eac1 --- /dev/null +++ b/docs/tests/UISplitViewController+Action.swift.html @@ -0,0 +1,447 @@ + + + +UISplitViewController+Action.swift - Slather + + + +
Slather logo
+

+Coverage for "UISplitViewController+Action.swift" : 100.00% +

+

(41 of 41 relevant lines covered)

+

RouteComposer/Classes/Actions/UISplitViewController+Action.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-09-18.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Actions for `UISplitViewController`
9
public extension ContainerViewController where Self: UISplitViewController {
10
11
    /// Presents a view controller as a master in the `UISplitViewController`
12
    static func setAsMaster() -> SplitViewControllerActions.SetAsMasterAction<Self> {
5x
13
        return SplitViewControllerActions.SetAsMasterAction()
5x
14
    }
5x
15
16
    /// Presents a view controller as a detail in the `UISplitViewController`
17
    static func pushToDetails() -> SplitViewControllerActions.PushToDetailsAction<Self> {
9x
18
        return SplitViewControllerActions.PushToDetailsAction()
9x
19
    }
9x
20
21
}
22
23
/// Actions for `UISplitViewController`
24
public struct SplitViewControllerActions {
25
26
    /// Presents a master view controller in the `UISplitViewController`
27
    public struct SetAsMasterAction<ViewController: UISplitViewController>: ContainerAction {
28
29
        /// Constructor
30
        init() {
5x
31
        }
5x
32
33
        public func perform(embedding viewController: UIViewController, in childViewControllers: inout [UIViewController]) throws {
4x
34
            integrate(viewController: viewController, in: &childViewControllers)
4x
35
        }
4x
36
37
        public func perform(with viewController: UIViewController,
38
                            on splitViewController: ViewController,
39
                            animated: Bool,
40
                            completion: @escaping (_: ActionResult) -> Void) {
1x
41
            integrate(viewController: viewController, in: &splitViewController.viewControllers)
1x
42
            completion(.continueRouting)
1x
43
        }
1x
44
45
        private func integrate(viewController: UIViewController, in childViewControllers: inout [UIViewController]) {
5x
46
            if childViewControllers.isEmpty {
5x
47
                childViewControllers.append(viewController)
3x
48
            } else {
5x
49
                childViewControllers[0] = viewController
2x
50
            }
5x
51
        }
5x
52
53
    }
54
55
    /// Presents a detail view controller in the `UISplitViewController`
56
    public struct PushToDetailsAction<ViewController: UISplitViewController>: ContainerAction {
57
58
        /// Constructor
59
        init() {
9x
60
        }
9x
61
62
        public func perform(embedding viewController: UIViewController, in childViewControllers: inout [UIViewController]) throws {
4x
63
            guard !childViewControllers.isEmpty else {
4x
64
                throw RoutingError.compositionFailed(.init("Master view controller is not set in " +
1x
65
                        "UISplitViewController to present a detail view controller \(viewController)."))
1x
66
            }
3x
67
            childViewControllers.append(viewController)
3x
68
        }
3x
69
70
        public func perform(with viewController: UIViewController,
71
                            on splitViewController: ViewController,
72
                            animated: Bool,
73
                            completion: @escaping (_: ActionResult) -> Void) {
5x
74
            guard !splitViewController.viewControllers.isEmpty else {
5x
75
                completion(.failure(RoutingError.compositionFailed(.init("Master view controller is not set in " +
1x
76
                        "\(splitViewController) to present a detail view controller \(viewController)."))))
1x
77
                return
1x
78
            }
4x
79
4x
80
            splitViewController.showDetailViewController(viewController, sender: nil)
4x
81
            completion(.continueRouting)
4x
82
        }
4x
83
    }
84
85
}
+
+ + + diff --git a/docs/tests/UITabBarController+Action.swift.html b/docs/tests/UITabBarController+Action.swift.html new file mode 100644 index 000000000..1eaa67ba7 --- /dev/null +++ b/docs/tests/UITabBarController+Action.swift.html @@ -0,0 +1,487 @@ + + + +UITabBarController+Action.swift - Slather + + + +
Slather logo
+

+Coverage for "UITabBarController+Action.swift" : 100.00% +

+

(35 of 35 relevant lines covered)

+

RouteComposer/Classes/Actions/UITabBarController+Action.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-09-18.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// Actions for `UITabBarController`
9
public extension ContainerViewController where Self: UITabBarController {
10
11
    /// Adds a `UIViewController` to a `UITabBarController`
12
    ///
13
    ///   - tabIndex: index of a tab.
14
    ///   - replacing: should be set to `true` if an existing view controller should be replaced.
15
    ///     If condition has not been passed, a view controller
16
    ///   will be added after the latest one.
17
    static func add(at tabIndex: Int, replacing: Bool = false) -> TabBarControllerActions.AddTabAction<Self> {
8x
18
        return TabBarControllerActions.AddTabAction(at: tabIndex, replacing: replacing)
8x
19
    }
8x
20
21
    /// Adds a `UIViewController` to a `UITabBarController`
22
    ///
23
    ///   - tabIndex: index of a tab.
24
    ///     If condition has not been passed, a view controller
25
    ///   will be added after the latest one.
26
    static func add(at tabIndex: Int? = nil) -> TabBarControllerActions.AddTabAction<Self> {
26x
27
        return TabBarControllerActions.AddTabAction(at: tabIndex)
26x
28
    }
26x
29
30
}
31
32
/// Actions for `UITabBarController`
33
public struct TabBarControllerActions {
34
35
    /// Integrates a `UIViewController` in to a `UITabBarController`
36
    public struct AddTabAction<ViewController: UITabBarController>: ContainerAction {
37
38
        let tabIndex: Int?
39
40
        let replacing: Bool
41
42
        /// Constructor
43
        ///
44
        /// - Parameters:
45
        ///   - tabIndex: index of the tab after which one a view controller should be added.
46
        ///   - replacing: instead of adding a view controller after the tabIndex - replace the one at that index.
47
        init(at tabIndex: Int, replacing: Bool = false) {
8x
48
            self.tabIndex = tabIndex
8x
49
            self.replacing = replacing
8x
50
        }
8x
51
52
        /// Constructor
53
        ///
54
        ///   - tabIndex: index of the tab after which one a view controller should be added.
55
        ///     If has not been passed - a view controller
56
        ///   will be added after the latest one.
57
        init(at tabIndex: Int? = nil) {
26x
58
            self.tabIndex = tabIndex
26x
59
            self.replacing = false
26x
60
        }
26x
61
62
        public func perform(embedding viewController: UIViewController,
63
                            in childViewControllers: inout [UIViewController]) {
22x
64
            setup(viewController: viewController, at: &childViewControllers, tabIndex: tabIndex)
22x
65
        }
22x
66
67
        public func perform(with viewController: UIViewController,
68
                            on tabBarController: ViewController,
69
                            animated: Bool,
70
                            completion: @escaping(_: ActionResult) -> Void) {
5x
71
            var tabViewControllers = tabBarController.viewControllers ?? []
5x
72
            setup(viewController: viewController, at: &tabViewControllers, tabIndex: tabIndex)
5x
73
            tabBarController.setViewControllers(tabViewControllers, animated: animated)
5x
74
5x
75
            return completion(.continueRouting)
5x
76
        }
5x
77
78
        private func setup(viewController: UIViewController,
79
                           at childViewControllers: inout [UIViewController], tabIndex: Int?) {
27x
80
            if let tabIndex = tabIndex, tabIndex < childViewControllers.count {
27x
81
                if replacing {
6x
82
                    childViewControllers[tabIndex] = viewController
4x
83
                } else {
6x
84
                    childViewControllers.insert(viewController, at: tabIndex)
2x
85
                }
6x
86
            } else {
27x
87
                childViewControllers.append(viewController)
21x
88
            }
27x
89
        }
27x
90
91
    }
92
93
}
+
+ + + diff --git a/docs/tests/UIViewController+Action.swift.html b/docs/tests/UIViewController+Action.swift.html new file mode 100644 index 000000000..98dce392a --- /dev/null +++ b/docs/tests/UIViewController+Action.swift.html @@ -0,0 +1,952 @@ + + + +UIViewController+Action.swift - Slather + + + +
Slather logo
+

+Coverage for "UIViewController+Action.swift" : 97.53% +

+

(79 of 81 relevant lines covered)

+

RouteComposer/Classes/Actions/UIViewController+Action.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 2018-09-18.
3
//
4
5
import Foundation
6
import UIKit
7
8
/// A wrapper for general actions that can be applied to any `UIViewController`
9
public struct GeneralAction {
10
11
    /// Replaces the root view controller in the key `UIWindow`
12
    ///
13
    /// - Parameters:
14
    ///   - windowProvider: `WindowProvider` instance
15
    ///   - animationOptions: Set of `UIView.AnimationOptions`. Transition will happen without animation if not provided.
16
    ///   - duration: Transition duration.
17
    public static func replaceRoot(windowProvider: WindowProvider = KeyWindowProvider(),
18
                                   animationOptions: UIView.AnimationOptions? = nil,
19
                                   duration: TimeInterval = 0.3) -> ViewControllerActions.ReplaceRootAction {
51x
20
        return ViewControllerActions.ReplaceRootAction(windowProvider: windowProvider, animationOptions: animationOptions, duration: duration)
51x
21
    }
51x
22
23
    /// Presents a view controller modally
24
    ///
25
    /// - Parameters:
26
    ///   - presentationStyle: `UIModalPresentationStyle` setting, default value: .fullScreen
27
    ///   - transitionStyle: `UIModalTransitionStyle` setting, default value: .coverVertical
28
    ///   - transitioningDelegate: `UIViewControllerTransitioningDelegate` instance to be used during the transition
29
    ///   - preferredContentSize: The preferredContentSize is used for any container laying out a child view controller.
30
    ///   - popoverControllerConfigurationBlock: Block to configure `UIPopoverPresentationController`.
31
    public static func presentModally(presentationStyle: UIModalPresentationStyle? = .fullScreen,
32
                                      transitionStyle: UIModalTransitionStyle? = .coverVertical,
33
                                      transitioningDelegate: UIViewControllerTransitioningDelegate? = nil,
34
                                      preferredContentSize: CGSize? = nil,
35
                                      popoverConfiguration: ((_: UIPopoverPresentationController) -> Void)? = nil) -> ViewControllerActions.PresentModallyAction {
33x
36
        return ViewControllerActions.PresentModallyAction(presentationStyle: presentationStyle,
33x
37
                transitionStyle: transitionStyle,
33x
38
                transitioningDelegate: transitioningDelegate,
33x
39
                preferredContentSize: preferredContentSize,
33x
40
                popoverConfiguration: popoverConfiguration)
33x
41
    }
33x
42
43
}
44
45
/// A wrapper for general actions that can be applied to any `UIViewController`
46
public struct ViewControllerActions {
47
48
    /// Presents a view controller modally
49
    public struct PresentModallyAction: Action {
50
51
        /// `UIModalPresentationStyle` setting
52
        public let presentationStyle: UIModalPresentationStyle?
53
54
        /// `UIModalTransitionStyle` setting
55
        public let transitionStyle: UIModalTransitionStyle?
56
57
        /// The preferredContentSize is used for any container laying out a child view controller.
58
        public let preferredContentSize: CGSize?
59
60
        /// Block to configure `UIPopoverPresentationController`
61
        public let popoverControllerConfigurationBlock: ((_: UIPopoverPresentationController) -> Void)?
62
63
        /// `UIViewControllerTransitioningDelegate` instance to be used during the transition
64
        private(set) public weak var transitioningDelegate: UIViewControllerTransitioningDelegate?
65
66
        /// Constructor
67
        ///
68
        /// - Parameters:
69
        ///   - presentationStyle: `UIModalPresentationStyle` setting, default value: .fullScreen
70
        ///   - transitionStyle: `UIModalTransitionStyle` setting, default value: .coverVertical
71
        ///   - transitioningDelegate: `UIViewControllerTransitioningDelegate` instance to be used during the transition
72
        ///   - preferredContentSize: The preferredContentSize is used for any container laying out a child view controller.
73
        ///   - popoverControllerConfigurationBlock: Block to configure `UIPopoverPresentationController`.
74
        init(presentationStyle: UIModalPresentationStyle? = .fullScreen,
75
             transitionStyle: UIModalTransitionStyle? = .coverVertical,
76
             transitioningDelegate: UIViewControllerTransitioningDelegate? = nil,
77
             preferredContentSize: CGSize? = nil,
78
             popoverConfiguration: ((_: UIPopoverPresentationController) -> Void)? = nil) {
34x
79
            self.presentationStyle = presentationStyle
34x
80
            self.transitionStyle = transitionStyle
34x
81
            self.transitioningDelegate = transitioningDelegate
34x
82
            self.preferredContentSize = preferredContentSize
34x
83
            self.popoverControllerConfigurationBlock = popoverConfiguration
34x
84
        }
34x
85
86
        public func perform(with viewController: UIViewController,
87
                            on existingController: UIViewController,
88
                            animated: Bool,
89
                            completion: @escaping (_: ActionResult) -> Void) {
22x
90
            guard existingController.presentedViewController == nil else {
22x
91
                completion(.failure(RoutingError.compositionFailed(.init("\(existingController) is " +
1x
92
                        "already presenting a view controller."))))
1x
93
                return
1x
94
            }
21x
95
            if let presentationStyle = presentationStyle {
21x
96
                viewController.modalPresentationStyle = presentationStyle
21x
97
            }
21x
98
            if let transitionStyle = transitionStyle {
21x
99
                viewController.modalTransitionStyle = transitionStyle
21x
100
            }
21x
101
            if let transitioningDelegate = transitioningDelegate {
21x
102
                viewController.transitioningDelegate = transitioningDelegate
4x
103
            }
21x
104
            if let preferredContentSize = preferredContentSize {
21x
105
                viewController.preferredContentSize = preferredContentSize
1x
106
            }
21x
107
            if let popoverPresentationController = viewController.popoverPresentationController,
21x
108
               let popoverControllerConfigurationBlock = popoverControllerConfigurationBlock {
21x
109
                popoverControllerConfigurationBlock(popoverPresentationController)
1x
110
            }
21x
111
21x
112
            existingController.present(viewController, animated: animated, completion: {
21x
113
                completion(.continueRouting)
21x
114
            })
21x
115
        }
21x
116
117
    }
118
119
    /// Replaces the root view controller in the key `UIWindow`
120
    public struct ReplaceRootAction: Action {
121
122
        let windowProvider: WindowProvider
123
124
        let animationOptions: UIView.AnimationOptions?
125
126
        let duration: TimeInterval
127
128
        /// Constructor
129
        ///
130
        /// - Parameters:
131
        ///   - windowProvider: `WindowProvider` instance
132
        ///   - animationOptions: Set of `UIView.AnimationOptions`. Transition will happen without animation if not provided.
133
        ///   - duration: Transition duration.
134
        init(windowProvider: WindowProvider = KeyWindowProvider(), animationOptions: UIView.AnimationOptions? = nil, duration: TimeInterval = 0.3) {
53x
135
            self.windowProvider = windowProvider
53x
136
            self.animationOptions = animationOptions
53x
137
            self.duration = duration
53x
138
        }
53x
139
140
        public func perform(with viewController: UIViewController,
141
                            on existingController: UIViewController,
142
                            animated: Bool,
143
                            completion: @escaping(_: ActionResult) -> Void) {
21x
144
            guard let window = windowProvider.window else {
21x
145
                completion(.failure(RoutingError.compositionFailed(.init("Window was not found."))))
!
146
                return
!
147
            }
21x
148
            guard window.rootViewController == existingController else {
21x
149
                completion(.failure(RoutingError.compositionFailed(.init("Action should be applied to the root view " +
1x
150
                        "controller, got \(String(describing: existingController)) instead."))))
1x
151
                return
1x
152
            }
20x
153
20x
154
            guard animated, let animationOptions = animationOptions, duration > 0 else {
20x
155
                window.rootViewController = viewController
8x
156
                window.makeKeyAndVisible()
8x
157
                return completion(.continueRouting)
8x
158
            }
12x
159
12x
160
            UIView.transition(with: window, duration: duration, options: animationOptions, animations: {
12x
161
                let oldAnimationState = UIView.areAnimationsEnabled
12x
162
                UIView.setAnimationsEnabled(false)
12x
163
                window.rootViewController = viewController
12x
164
                window.rootViewController?.view.setNeedsLayout()
12x
165
                window.makeKeyAndVisible()
12x
166
                UIView.setAnimationsEnabled(oldAnimationState)
12x
167
            })
12x
168
            completion(.continueRouting)
12x
169
        }
12x
170
171
    }
172
173
    struct NilAction: Action {
174
175
        // Constructor
176
        init() {
121x
177
        }
121x
178
179
        // Does nothing
180
        func perform(with viewController: UIViewController, on existingController: UIViewController, animated: Bool, completion: @escaping (ActionResult) -> Void) {
15x
181
            completion(.continueRouting)
15x
182
        }
15x
183
184
    }
185
186
}
+
+ + + diff --git a/docs/tests/UIViewController+Extension.swift.html b/docs/tests/UIViewController+Extension.swift.html new file mode 100644 index 000000000..f75bc9b6f --- /dev/null +++ b/docs/tests/UIViewController+Extension.swift.html @@ -0,0 +1,527 @@ + + + +UIViewController+Extension.swift - Slather + + + +
Slather logo
+

+Coverage for "UIViewController+Extension.swift" : 98.63% +

+

(72 of 73 relevant lines covered)

+

RouteComposer/Classes/Extensions/UIViewController+Extension.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 19/12/2017.
3
// Copyright (c) 2017 HBC Tech. All rights reserved.
4
//
5
6
import UIKit
7
8
public extension UIViewController {
9
10
    /// Iterates through the view controller stack to finds a `UIViewController` instance.
11
    ///
12
    /// - Parameters:
13
    ///   - viewController: A `UIViewController` instance to start from.
14
    ///   - options: A combination of `SearchOptions`.
15
    ///   - predicate: A block that should return `true` if the `UIViewController` instance provided is the
16
    ///     one that is being searched for.
17
    /// - Returns: A `UIViewController` instance if found, `nil` otherwise.
18
    static func findViewController(in viewController: UIViewController,
19
                                   options: SearchOptions = .currentAndUp,
20
                                   using predicate: (UIViewController) -> Bool) -> UIViewController? {
1160x
21
        guard !viewController.isBeingDismissed else {
1160x
22
            return nil
!
23
        }
1160x
24
1160x
25
        if options.contains(.current), predicate(viewController) {
1160x
26
            return viewController
265x
27
        }
899x
28
899x
29
        if options.contains(.parent),
899x
30
           let parentViewController = viewController.parent,
899x
31
           let foundViewController = findViewController(in: parentViewController,
899x
32
                   options: [.current, .parent],
899x
33
                   using: predicate) {
899x
34
            return foundViewController
6x
35
        }
893x
36
893x
37
        if let container = viewController as? ContainerViewController, options.contains(.visible) || options.contains(.contained) {
893x
38
            var viewControllers: [[UIViewController]] = []
550x
39
            viewControllers.append(container.visibleViewControllers)
550x
40
            if options.contains(.contained) {
550x
41
                viewControllers.append(container.containedViewControllers)
294x
42
            }
550x
43
            for currentViewController in Array(viewControllers.joined()).uniqueElements() {
694x
44
                if let foundViewController = findViewController(in: currentViewController,
694x
45
                        options: options.contains(.visible) ? .currentVisibleOnly : [.current, .contained],
694x
46
                        using: predicate) {
694x
47
                    return foundViewController
333x
48
                }
361x
49
            }
361x
50
        }
560x
51
560x
52
        if options.contains(.presented),
560x
53
           let presentedViewController = viewController.presentedViewController {
560x
54
            let presentedOptions = options.subtracting(.presenting)
18x
55
            if let foundViewController = findViewController(in: presentedViewController, options: presentedOptions, using: predicate) {
18x
56
                return foundViewController
3x
57
            }
15x
58
        }
557x
59
557x
60
        if options.contains(.presenting),
557x
61
           let presentingViewController = viewController.presentingViewController {
557x
62
            let presentingOptions = options.subtracting(.presented)
45x
63
            if let foundViewController = findViewController(in: presentingViewController, options: presentingOptions, using: predicate) {
45x
64
                return foundViewController
3x
65
            }
42x
66
        }
554x
67
554x
68
        return nil
554x
69
    }
557x
70
71
}
72
73
extension UIViewController {
74
75
    var allPresentedViewControllers: [UIViewController] {
94x
76
        var allPresentedViewControllers: [UIViewController] = []
94x
77
        var presentingViewController = self
94x
78
94x
79
        while let presentedViewController = presentingViewController.presentedViewController, !presentedViewController.isBeingDismissed {
94x
80
            allPresentedViewControllers.append(presentedViewController)
18x
81
            presentingViewController = presentedViewController
18x
82
        }
94x
83
94x
84
        return allPresentedViewControllers
94x
85
    }
94x
86
87
    var allParents: [UIViewController] {
217x
88
        var allParents: [UIViewController] = []
217x
89
        var currentViewController: UIViewController? = self.parent
217x
90
        while let currentParent = currentViewController {
217x
91
            allParents.append(currentParent)
180x
92
            currentViewController = currentParent.parent
180x
93
        }
217x
94
        return allParents
217x
95
    }
217x
96
97
    static func findContainer<Container: ContainerViewController>(of viewController: UIViewController) -> Container? {
19x
98
        return [[viewController], viewController.allParents].joined().first(where: { $0 is Container }) as? Container
31x
99
    }
19x
100
101
}
+
+ + + diff --git a/docs/tests/UIWindow+Extension.swift.html b/docs/tests/UIWindow+Extension.swift.html new file mode 100644 index 000000000..5ae71c771 --- /dev/null +++ b/docs/tests/UIWindow+Extension.swift.html @@ -0,0 +1,137 @@ + + + +UIWindow+Extension.swift - Slather + + + +
Slather logo
+

+Coverage for "UIWindow+Extension.swift" : 100.00% +

+

(9 of 9 relevant lines covered)

+

RouteComposer/Classes/Extensions/UIWindow+Extension.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
// Created by Eugene Kazaev on 19/12/2017.
3
// Copyright (c) 2017 HBC Tech. All rights reserved.
4
//
5
6
import Foundation
7
import UIKit
8
9
/// `UIWindow` helper functions.
10
public extension UIWindow {
11
12
    /// The topmost `UIViewController` in the view controller stack.
13
    var topmostViewController: UIViewController? {
318x
14
        var topmostViewController = rootViewController
318x
15
318x
16
        while let presentedViewController = topmostViewController?.presentedViewController, !presentedViewController.isBeingDismissed {
318x
17
            topmostViewController = presentedViewController
135x
18
        }
318x
19
318x
20
        return topmostViewController
318x
21
    }
318x
22
23
}
+
+ + + diff --git a/docs/tests/XibFactory.swift.html b/docs/tests/XibFactory.swift.html new file mode 100644 index 000000000..48e0ec79a --- /dev/null +++ b/docs/tests/XibFactory.swift.html @@ -0,0 +1,197 @@ + + + +XibFactory.swift - Slather + + + +
Slather logo
+

+Coverage for "XibFactory.swift" : 100.00% +

+

(8 of 8 relevant lines covered)

+

RouteComposer/Classes/Factories/XibFactory.swift

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
//
2
//  XibFactory.swift
3
//  RouteComposer
4
//
5
//  Created by Eugene Kazaev on 09/02/2018.
6
//
7
8
import Foundation
9
import UIKit
10
11
/// The `Factory` that creates a `UIViewController` from a Xib file.
12
public struct XibFactory<VC: UIViewController, C>: Factory {
13
14
    /// A Xib file name
15
    public let nibName: String?
16
17
    /// A `Bundle` instance
18
    public let bundle: Bundle?
19
20
    /// Constructor
21
    ///
22
    /// - Parameters:
23
    ///   - nibName: A Xib file name
24
    ///   - bundle: A `Bundle` instance if needed
25
    public init(nibName: String? = nil, bundle: Bundle? = nil) {
7x
26
        self.nibName = nibName
7x
27
        self.bundle = bundle
7x
28
    }
7x
29
30
    public func build(with context: C) throws -> VC {
4x
31
        let viewController = ViewController(nibName: nibName, bundle: bundle)
4x
32
        return viewController
4x
33
    }
4x
34
35
}
+
+ + + diff --git a/docs/tests/highlight.pack.js b/docs/tests/highlight.pack.js new file mode 100644 index 000000000..1fbbace20 --- /dev/null +++ b/docs/tests/highlight.pack.js @@ -0,0 +1 @@ +!function(e){"undefined"!=typeof exports?e(exports):(window.hljs=e({}),"function"==typeof define&&define.amd&&define("hljs",[],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&").replace(//gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){return/no-?highlight|plain|text/.test(e)}function i(e){var n,t,r,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=/\blang(?:uage)?-([\w-]+)\b/.exec(i))return E(t[1])?t[1]:"no-highlight";for(i=i.split(/\s+/),n=0,r=i.length;r>n;n++)if(E(i[n])||a(i[n]))return i[n]}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3==i.nodeType?a+=i.nodeValue.length:1==i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset"}function u(e){f+=""}function c(e){("start"==e.event?o:u)(e.node)}for(var s=0,f="",l=[];e.length||r.length;){var g=i();if(f+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){l.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g==e&&g.length&&g[0].offset==s);l.reverse().forEach(o)}else"start"==g[0].event?l.push(g[0].node):l.pop(),c(g.splice(0,1)[0])}return f+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\b\w+\b/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var f=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=f.length?t(f.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){for(var t=0;t";return i+=e+'">',i+n+o}function p(){if(!L.k)return n(B);var e="",t=0;L.lR.lastIndex=0;for(var r=L.lR.exec(B);r;){e+=n(B.substr(t,r.index-t));var a=g(L,r);a?(y+=a[1],e+=h(a[0],n(r[0]))):e+=n(r[0]),t=L.lR.lastIndex,r=L.lR.exec(B)}return e+n(B.substr(t))}function d(){if(L.sL&&!x[L.sL])return n(B);var e=L.sL?f(L.sL,B,!0,M[L.sL]):l(B);return L.r>0&&(y+=e.r),"continuous"==L.subLanguageMode&&(M[L.sL]=e.top),h(e.language,e.value,!1,!0)}function b(){return void 0!==L.sL?d():p()}function v(e,t){var r=e.cN?h(e.cN,"",!0):"";e.rB?(k+=r,B=""):e.eB?(k+=n(t)+r,B=""):(k+=r,B=t),L=Object.create(e,{parent:{value:L}})}function m(e,t){if(B+=e,void 0===t)return k+=b(),0;var r=o(t,L);if(r)return k+=b(),v(r,t),r.rB?0:t.length;var a=u(L,t);if(a){var i=L;i.rE||i.eE||(B+=t),k+=b();do L.cN&&(k+=""),y+=L.r,L=L.parent;while(L!=a.parent);return i.eE&&(k+=n(t)),B="",a.starts&&v(a.starts,""),i.rE?0:t.length}if(c(t,L))throw new Error('Illegal lexeme "'+t+'" for mode "'+(L.cN||"")+'"');return B+=t,t.length||1}var N=E(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,L=i||N,M={},k="";for(R=L;R!=N;R=R.parent)R.cN&&(k=h(R.cN,"",!0)+k);var B="",y=0;try{for(var C,j,I=0;;){if(L.t.lastIndex=I,C=L.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}for(m(t.substr(I)),R=L;R.parent;R=R.parent)R.cN&&(k+="");return{r:y,value:k,language:e,top:L}}catch(O){if(-1!=O.message.indexOf("Illegal"))return{r:0,value:n(t)};throw O}}function l(e,t){t=t||w.languages||Object.keys(x);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(E(n)){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function g(e){return w.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,w.tabReplace)})),w.useBR&&(e=e.replace(/\n/g,"
")),e}function h(e,n,t){var r=n?R[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n=i(e);if(!a(n)){var t;w.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):t=e;var r=t.textContent,o=n?f(n,r,!0):l(r),s=u(t);if(s.length){var p=document.createElementNS("http://www.w3.org/1999/xhtml","div");p.innerHTML=o.value,o.value=c(s,u(p),r)}o.value=g(o.value),e.innerHTML=o.value,e.className=h(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){w=o(w,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){R[e]=n})}function N(){return Object.keys(x)}function E(e){return x[e]||x[R[e]]}var w={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},x={},R={};return e.highlight=f,e.highlightAuto=l,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=E,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="\\b(0[xX][a-fA-F0-9]+|(\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",bK:"TODO FIXME NOTE BUG XXX",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e});hljs.registerLanguage("json",function(e){var t={literal:"true false null"},i=[e.QSM,e.CNM],l={cN:"value",e:",",eW:!0,eE:!0,c:i,k:t},c={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:!0,eE:!0,c:[e.BE],i:"\\n",starts:l}],i:"\\S"},n={b:"\\[",e:"\\]",c:[e.inherit(l,{cN:null})],i:"\\S"};return i.splice(i.length,0,c,n),{c:i,k:t,i:"\\S"}});hljs.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"(AV|CA|CF|CG|CI|MK|MP|NS|UI)\\w+"},i={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},o=/[a-zA-Z@][a-zA-Z0-9_]*/,n="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:i,l:o,i:""}]}]},{cN:"class",b:"("+n.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:n,l:o,c:[e.UTM]},{cN:"variable",b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"[a-z\\d_]*_t"},r={keyword:"false int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using true class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept nullptr static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong",built_in:"std string cin cout cerr clog stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf"};return{aliases:["c","cc","h","c++","h++","hpp"],k:r,i:""]',k:"include",i:"\\n"},t.CLCM]},{b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:r,c:["self",e]},{b:t.IR+"::",k:r},{bK:"new throw return else",r:0},{cN:"function",b:"("+t.IR+"\\s+)+"+t.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:t.IR+"\\s*\\(",rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:r,r:0,c:[t.CBCM]},t.CLCM,t.CBCM]}]}}); \ No newline at end of file diff --git a/docs/tests/index.html b/docs/tests/index.html new file mode 100644 index 000000000..cadf66736 --- /dev/null +++ b/docs/tests/index.html @@ -0,0 +1,767 @@ + + + +RouteComposer.xcodeproj - Slather + + + +
Slather logo
+

Files for "RouteComposer.xcodeproj"

+

+Total Coverage : 83.27% +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
%FileLinesRelevantCoveredMissed
50.00AbstractFactory.swift48633
100.00Action.swift32330
0.00ActionResult.swift35606
84.62UINavigationController+Action.swift9839336
100.00UISplitViewController+Action.swift8541410
100.00UITabBarController+Action.swift9335350
97.53UIViewController+Action.swift18681792
100.00ChainAssembly.swift24330
39.13CompleteFactoryAssembly.swift108461828
55.88ContainerStepAssembly.swift90341915
100.00ActionConnectingAssembly.swift3618180
100.00ActionToStepIntegrator.swift6021210
100.00BaseEntitiesCollector.swift2811110
67.24CompleteFactoryChainAssembly.swift112583919
100.00ContainerStepChainAssembly.swift4316160
100.00GenericStepAssembly.swift4712120
86.36LastStepInChainAssembly.swift4122193
81.25StepChainAssembly.swift4316133
100.00TaskCollector.swift3918180
100.00StepAssembly.swift9134340
91.49SwitchAssembly.swift14347434
100.00ChildCoordinator.swift3110100
69.23ContainerFactory.swift8726188
20.00ContextTask.swift8715312
100.00DestinationStep.swift6018180
100.00Array+Extension.swift4525250
95.65NavigationController+Extension.swift4523221
58.06SplitViewController+Extension.swift67311813
76.92TabBarViewController+Extension.swift4826206
98.63UIViewController+Extension.swift10173721
100.00UIWindow+Extension.swift23990
0.00ContextAccepting.swift37202
100.00ContextSettingTask.swift24880
100.00DismissalMethodProvidingContextTask.swift29660
66.67Dismissible.swift8421147
96.77NavigationDelayInterceptor.swift7931301
100.00PresentingFinder.swift25660
71.79SingleNavigationRouter.swift87392811
90.00ClassNameFactory.swift4920182
100.00CompleteFactory.swift4320200
100.00FinderFactory.swift3512120
78.95NavigationControllerFactory.swift4019154
100.00NilFactory.swift30880
100.00SimpleContainerFactory.swift37440
81.48SplitControllerFactory.swift6027225
71.43StoryboardFactory.swift5828208
78.95TabBarControllerFactory.swift4019154
100.00XibFactory.swift35880
65.22Factory.swift7423158
0.00Finder.swift47606
100.00ClassFinder.swift40990
66.67ClassWithContextFinder.swift42963
100.00InstanceFinder.swift27660
100.00NilFinder.swift27550
0.00CustomWindowProvider.swift19303
100.00DefaultStackIterator.swift6221210
77.78KeyWindowProvider.swift23972
100.00StackIteratingFinder.swift4510100
100.00InlineTasks.swift10636360
0.00InterceptorResult.swift34606
50.00DefaultLogger.swift69381919
0.00PostRoutingTask.swift54606
50.00Router.swift52633
95.69DefaultRouter.swift2552092009
94.12BaseStep.swift8334322
94.89DefaultRouter+Extension.swift3031761679
100.00DelayedIntegrationFactory.swift4523230
57.14MainThreadChecking.swift21743
66.67PreparableEntity.swift22642
100.00SwitcherStep.swift3111110
81.25ContextTaskMultiplexer.swift3516133
86.49InterceptorMultiplexer.swift5237325
66.67PostRoutingTaskMultiplexer.swift24963
76.92ActionBox.swift4726206
86.67AnyFactoryBox.swift5115132
77.59ContainerActionBox.swift80584513
89.66ContainerFactoryBox.swift5129263
91.67ContextTaskBox.swift4124222
87.50FactoryBox.swift3516142
100.00FinderBox.swift3016160
88.89PostRoutingTaskBox.swift3418162
92.86RoutingInterceptorBox.swift4528262
16.00RoutingError.swift6125421
20.00RoutingInterceptor.swift10115312
100.00RoutingResult.swift32660
79.17SearchOptions.swift7724195
91.67GeneralStep.swift7836333
100.00NavigationControllerStep.swift16330
35.29SingleContainerStep.swift90341222
70.59SingleStep.swift90342410
0.00SplitControllerStep.swift16303
100.00TabBarControllerStep.swift16330
+
+ + + diff --git a/docs/tests/list.min.js b/docs/tests/list.min.js new file mode 100644 index 000000000..8327aaf13 --- /dev/null +++ b/docs/tests/list.min.js @@ -0,0 +1 @@ +var List=function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var r={};return e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=11)}([function(t,e,r){function n(t){if(!t||!t.nodeType)throw new Error("A DOM element reference is required");this.el=t,this.list=t.classList}var i=r(4),s=/\s+/;Object.prototype.toString;t.exports=function(t){return new n(t)},n.prototype.add=function(t){if(this.list)return this.list.add(t),this;var e=this.array(),r=i(e,t);return~r||e.push(t),this.el.className=e.join(" "),this},n.prototype.remove=function(t){if(this.list)return this.list.remove(t),this;var e=this.array(),r=i(e,t);return~r&&e.splice(r,1),this.el.className=e.join(" "),this},n.prototype.toggle=function(t,e){return this.list?("undefined"!=typeof e?e!==this.list.toggle(t,e)&&this.list.toggle(t):this.list.toggle(t),this):("undefined"!=typeof e?e?this.add(t):this.remove(t):this.has(t)?this.remove(t):this.add(t),this)},n.prototype.array=function(){var t=this.el.getAttribute("class")||"",e=t.replace(/^\s+|\s+$/g,""),r=e.split(s);return""===r[0]&&r.shift(),r},n.prototype.has=n.prototype.contains=function(t){return this.list?this.list.contains(t):!!~i(this.array(),t)}},function(t,e,r){var n=window.addEventListener?"addEventListener":"attachEvent",i=window.removeEventListener?"removeEventListener":"detachEvent",s="addEventListener"!==n?"on":"",a=r(5);e.bind=function(t,e,r,i){t=a(t);for(var o=0;o0?setTimeout(function(){e(r,n,i)},1):(t.update(),n(i))};return e}},function(t,e){t.exports=function(t){return t.handlers.filterStart=t.handlers.filterStart||[],t.handlers.filterComplete=t.handlers.filterComplete||[],function(e){if(t.trigger("filterStart"),t.i=1,t.reset.filter(),void 0===e)t.filtered=!1;else{t.filtered=!0;for(var r=t.items,n=0,i=r.length;nv.page,a=new m(t[i],void 0,n),v.items.push(a),r.push(a)}return v.update(),r}},this.show=function(t,e){return this.i=t,this.page=e,v.update(),v},this.remove=function(t,e,r){for(var n=0,i=0,s=v.items.length;i-1&&r.splice(n,1),v},this.trigger=function(t){for(var e=v.handlers[t].length;e--;)v.handlers[t][e](v);return v},this.reset={filter:function(){for(var t=v.items,e=t.length;e--;)t[e].filtered=!1;return v},search:function(){for(var t=v.items,e=t.length;e--;)t[e].found=!1;return v}},this.update=function(){var t=v.items,e=t.length;v.visibleItems=[],v.matchingItems=[],v.templater.clear();for(var r=0;r=v.i&&v.visibleItems.lengthe},innerWindow:function(t,e,r){return t>=e-r&&t<=e+r},dotted:function(t,e,r,n,i,s,a){return this.dottedLeft(t,e,r,n,i,s)||this.dottedRight(t,e,r,n,i,s,a)},dottedLeft:function(t,e,r,n,i,s){return e==r+1&&!this.innerWindow(e,i,s)&&!this.right(e,n)},dottedRight:function(t,e,r,n,i,s,a){return!t.items[a-1].values().dotted&&(e==n&&!this.innerWindow(e,i,s)&&!this.right(e,n))}},a=function(e,r,n){i.bind(e,"click",function(){t.show((r-1)*n+1,n)})};return function(r){var n=new s(t.listContainer.id,{listClass:r.paginationClass||"pagination",item:"
  • ",valueNames:["page","dotted"],searchClass:"pagination-search-that-is-not-supposed-to-exist",sortClass:"pagination-sort-that-is-not-supposed-to-exist"});t.on("updated",function(){e(n,r)}),e(n,r)}}},function(t,e,r){t.exports=function(t){var e=r(2)(t),n=function(t){for(var e=t.childNodes,r=[],n=0,i=e.length;n0?setTimeout(function(){s(e,r)},1):(t.update(),t.trigger("parseComplete"))};return t.handlers.parseComplete=t.handlers.parseComplete||[],function(){var e=n(t.list),r=t.valueNames;t.indexAsync?s(e,r):i(e,r)}}},function(t,e){t.exports=function(t){var e,r,n,i,s={resetList:function(){t.i=1,t.templater.clear(),i=void 0},setOptions:function(t){2==t.length&&t[1]instanceof Array?r=t[1]:2==t.length&&"function"==typeof t[1]?(r=void 0,i=t[1]):3==t.length?(r=t[1],i=t[2]):r=void 0},setColumns:function(){0!==t.items.length&&void 0===r&&(r=void 0===t.searchColumns?s.toArray(t.items[0].values()):t.searchColumns)},setSearchString:function(e){e=t.utils.toString(e).toLowerCase(),e=e.replace(/[-[\]{}()*+?.,\\^$|#]/g,"\\$&"),n=e},toArray:function(t){var e=[];for(var r in t)e.push(r);return e}},a={list:function(){for(var e=0,r=t.items.length;e-1))},reset:function(){t.reset.search(),t.searched=!1}},o=function(e){return t.trigger("searchStart"),s.resetList(),s.setSearchString(e),s.setOptions(arguments),s.setColumns(),""===n?a.reset():(t.searched=!0,i?i(n,r):a.list()),t.update(),t.trigger("searchComplete"),t.visibleItems};return t.handlers.searchStart=t.handlers.searchStart||[],t.handlers.searchComplete=t.handlers.searchComplete||[],t.utils.events.bind(t.utils.getByClass(t.listContainer,t.searchClass),"keyup",function(e){var r=e.target||e.srcElement,n=""===r.value&&!t.searched;n||o(r.value)}),t.utils.events.bind(t.utils.getByClass(t.listContainer,t.searchClass),"input",function(t){var e=t.target||t.srcElement;""===e.value&&o("")}),o}},function(t,e){t.exports=function(t){var e={els:void 0,clear:function(){for(var r=0,n=e.els.length;r]/g.exec(e)){var s=document.createElement("tbody");return s.innerHTML=e,s.firstChild}if(e.indexOf("<")!==-1){var a=document.createElement("div");return a.innerHTML=e,a.firstChild}var o=document.getElementById(t.item);if(o)return o}},this.get=function(e,n){r.create(e);for(var i={},s=0,a=n.length;s=1;)t.list.removeChild(t.list.firstChild)},n()};t.exports=function(t){return new r(t)}},function(t,e){t.exports=function(t,e){var r=t.getAttribute&&t.getAttribute(e)||null;if(!r)for(var n=t.attributes,i=n.length,s=0;s=48&&t<=57}function i(t,e){for(var r=(t+="").length,i=(e+="").length,s=0,l=0;s32)return!1;var o=i,l=function(){var t,r={};for(t=0;t=p;b--){var w=l[t.charAt(b-1)];if(0===g?y[b]=(y[b+1]<<1|1)&w:y[b]=(y[b+1]<<1|1)&w|((v[b+1]|v[b])<<1|1)|v[b+1],y[b]&f){var x=n(g,b-1);if(x<=u){if(u=x,c=b-1,!(c>o))break;p=Math.max(1,2*o-c)}}}if(n(g+1,o)>u)break;v=y}return!(c<0)}}]); \ No newline at end of file diff --git a/docs/tests/logo.jpg b/docs/tests/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..74466044eb0eeccfaad9118a4fd9017444903535 GIT binary patch literal 64627 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 literal 0 HcmV?d00001 diff --git a/docs/tests/slather.css b/docs/tests/slather.css new file mode 100644 index 000000000..d09c00867 --- /dev/null +++ b/docs/tests/slather.css @@ -0,0 +1,316 @@ +/* -------------------------------------------------------- +Slather stylesheet + +version: 0.1 +author: Ikhsan Assaat (@ixnixnixn) +----------------------------------------------------------*/ + +/* General */ +html { + position: relative; + min-height: 100%; +} +body { + font: 16px "Helvetica", sans-serif; + margin: 0 0 120px; + color: #333; +} +.row { margin: 0 2em; } + +/* Header */ +header { margin-top: 1em; } +header img { width: auto; height: 120px; } + +/* Coverage */ +#reports > h2 { margin-bottom: 0; } +#reports > h4 { margin-top: 5px; } +.percentage { + padding: 4px ; + font-weight: bold; +} +.cov_high { color: #67CF7C; } +.cov_medium { color: #F89404; } +.cov_low { color: #F86769; } +.cov_title { margin-bottom: 0; } +.cov_subtitle { margin-top: 0.2em; } +.cov_filepath { font-style: italic; } + +/* Index Table */ +table.coverage_list { + width: 90%; + min-width: 400px; +} +table.coverage_list th, +table.coverage_list td { + padding: .6em .5em; + text-align: left; +} +table.coverage_list th.col_num { width: 70px; } +table.coverage_list th.col_percent { width: 75px; } +table.coverage_list thead, tfoot { background: #FDCD9B; } +table.coverage_list tbody tr:hover { background: #FCF2E6; } +table.coverage_list tbody td { border-bottom: 1px solid #CCC; } +table.coverage_list td a { + color: #333; + text-decoration: none; + border-bottom: 1px dotted; +} +table.coverage_list td a:hover { + border-bottom: none; +} + +/* Source Code */ +table.source_code { + width: 100%; + max-width: 1200px; + min-width: 400px; + font-size: 13px; + border-spacing: 0; + background: #FCF2E6; + padding: 1.2em 1em; + margin-bottom: 2em; +} + +table.source_code td { + padding-bottom: 0.3em; +} +table.source_code tr.missed td { background-color: rgba(248, 103, 105, 0.2); } +table.source_code tr.covered td { background-color: rgba(103, 207, 124, 0.2); } +table.source_code td.num { + border-right: 1px rgba(0,0,0,0.1) solid; + text-align: right; + padding-right: 1em; + width: 30px; +} +table.source_code td.src { + border-left: 1px rgba(255,255,255,0.7) solid; + padding-left: 1em; +} +table.source_code td.src pre { + white-space: pre-wrap; + white-space: -moz-pre-wrap; + white-space: -pre-wrap; + white-space: -o-pre-wrap; + word-wrap: break-word; + margin: 0; +} +table.source_code td.src pre code { font: 13px "Menlo", "Courier New"; } + +table.source_code td.coverage { + text-align: right; + padding-right: 0.5em; +} + +/* Footer */ +footer { + background-color: #67CDCF; + height: 80px; + + position: absolute; + left: 0; + bottom: 0; + width: 100%; + overflow:hidden; +} + +footer p, footer a { + color: #ffffff; + font-weight: bold; + text-align: center; +} + + +/* ---------------------------------------------------------- +Syntax Highlighting using highlight.js (https://highlightjs.org) +------------------------------------------------------------- */ +.hljs { + display: block; + overflow-x: auto; + -webkit-text-size-adjust: none; +} + +.hljs, +.hljs-subst, +.hljs-tag .hljs-title, +.nginx .hljs-title { + color: #333; +} + +.hljs-string, +.hljs-title, +.hljs-constant, +.hljs-parent, +.hljs-tag .hljs-value, +.hljs-rule .hljs-value, +.hljs-preprocessor, +.hljs-pragma, +.hljs-name, +.haml .hljs-symbol, +.ruby .hljs-symbol, +.ruby .hljs-symbol .hljs-string, +.hljs-template_tag, +.django .hljs-variable, +.smalltalk .hljs-class, +.hljs-addition, +.hljs-flow, +.hljs-stream, +.bash .hljs-variable, +.pf .hljs-variable, +.apache .hljs-tag, +.apache .hljs-cbracket, +.tex .hljs-command, +.tex .hljs-special, +.erlang_repl .hljs-function_or_atom, +.asciidoc .hljs-header, +.markdown .hljs-header, +.coffeescript .hljs-attribute, +.tp .hljs-variable { + color: #D14F4F; +} + +.smartquote, +.hljs-comment, +.hljs-annotation, +.diff .hljs-header, +.hljs-chunk, +.asciidoc .hljs-blockquote, +.markdown .hljs-blockquote { + color: #888; +} + +.hljs-number, +.hljs-date, +.hljs-regexp, +.hljs-literal, +.hljs-hexcolor, +.smalltalk .hljs-symbol, +.smalltalk .hljs-char, +.go .hljs-constant, +.hljs-change, +.lasso .hljs-variable, +.makefile .hljs-variable, +.asciidoc .hljs-bullet, +.markdown .hljs-bullet, +.asciidoc .hljs-link_url, +.markdown .hljs-link_url { + color: #05A5A8; +} + +.hljs-label, +.ruby .hljs-string, +.hljs-decorator, +.hljs-filter .hljs-argument, +.hljs-localvars, +.hljs-array, +.hljs-attr_selector, +.hljs-important, +.hljs-pseudo, +.hljs-pi, +.haml .hljs-bullet, +.hljs-doctype, +.hljs-deletion, +.hljs-envvar, +.hljs-shebang, +.apache .hljs-sqbracket, +.nginx .hljs-built_in, +.tex .hljs-formula, +.erlang_repl .hljs-reserved, +.hljs-prompt, +.asciidoc .hljs-link_label, +.markdown .hljs-link_label, +.vhdl .hljs-attribute, +.clojure .hljs-attribute, +.asciidoc .hljs-attribute, +.lasso .hljs-attribute, +.coffeescript .hljs-property, +.hljs-phony { + color: #087599; +} + +.hljs-keyword, +.hljs-id, +.hljs-title, +.hljs-built_in, +.css .hljs-tag, +.hljs-doctag, +.smalltalk .hljs-class, +.hljs-winutils, +.bash .hljs-variable, +.pf .hljs-variable, +.apache .hljs-tag, +.hljs-type, +.hljs-typename, +.tex .hljs-command, +.asciidoc .hljs-strong, +.markdown .hljs-strong, +.hljs-request, +.hljs-status, +.tp .hljs-data, +.tp .hljs-io { + font-weight: bold; +} + +.asciidoc .hljs-emphasis, +.markdown .hljs-emphasis, +.tp .hljs-units { + font-style: italic; +} + +.nginx .hljs-built_in { + font-weight: normal; +} + +.coffeescript .javascript, +.javascript .xml, +.lasso .markup, +.tex .hljs-formula, +.xml .javascript, +.xml .vbscript, +.xml .css, +.xml .hljs-cdata { + opacity: 0.5; +} + +/* ------------------------------------------------------- +Sorting & Filtering with List.js (http://www.listjs.com/) +------------------------------------------------------- */ + +input.search { + border:solid 1px #ccc; + border-radius: 4px; + padding:7px; + margin-bottom:10px; + font-size: 12px; +} +input.search:focus { + outline:none; + border-color:#aaa; +} + +th.sort::-moz-selection { background:transparent; } +th.sort::selection { background:transparent; } +th.sort { cursor:pointer; } +th.sort:after { + content:''; + display:inline-block; + width: 0; + height: 0; + position: relative; + top: -3px; + right: -6px; + border-width:0 4px 4px; + border-style:solid; + border-color:#404040 transparent; + visibility:hidden; +} + th.sort:hover:after { visibility:visible; } + th.sort.desc:after, + th.sort.asc:after, + th.sort.asc:hover:after { + visibility:visible; + opacity:0.6; +} + th.sort.desc:after { + border-bottom:none; + border-width:4px 4px 0; +}