Git Product home page Git Product logo

reswift-router's Introduction

Carthage compatible Platform support

A declarative router for ReSwift. Allows developers to declare routes in a similar manner as URLs are used on the web.

Using ReSwiftRouter you can navigate your app by defining the target location in the form of a URL-like sequence of identifiers:

mainStore.dispatch(
    SetRouteAction(["TabBarViewController", StatsViewController.identifier])
)

About ReSwiftRouter

ReSwiftRouter is still under development and the API is neither complete nor stable at this point.

When building apps with ReSwift you should aim to cause all state changes through actions - this includes changes to the navigation state.

This requires to store the current navigation state within the app state and to use actions to trigger changes to that state - both is provided ReSwiftRouter.

Installation

CocoaPods

You can install ReSwiftRouter via CocoaPods by adding it to your Podfile:

use_frameworks!

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

pod 'ReSwift'
pod 'ReSwiftRouter'

And run pod install.

Carthage

You can install ReSwiftRouter via Carthage by adding the following line to your Cartfile:

github "ReSwift/ReSwift-Router"

Configuration

Extend your app state to include the navigation state:

import ReSwiftRouter

struct AppState: StateType {
    // other application state
    var navigationState: NavigationState
}

After you've initialized your store, create an instance of Router, passing in a reference to the store and to the root Routable. Additionally you will need to provide a closure that describes how to access the navigationState of your application state:

router = Router(store: mainStore, rootRoutable: RootRoutable(routable: rootViewController)) { state in 
	state.select { $0.navigationState }
}

We'll discuss Routable in the next main section.

Calling the Navigation Reducer

The NavigationReducer is provided as part of ReSwiftRouter. You need to call it from within your top-level reducer. Here's a simple example from the specs:

struct AppReducer: Reducer {
    func handleAction(action: Action, state: FakeAppState?) -> FakeAppState {
        return FakeAppState(
            navigationState: NavigationReducer.handleAction(action, state: state?.navigationState)
        )
    }
}

This will make reducer handle all routing relevant actions.

Implementing Routable

ReSwiftRouter works with routes that are defined, similar to URLs, as a sequence of elements e.g. ["Home", "User", "UserDetail"].

ReSwiftRouter is agnostic of the UI framework you are using - it uses Routables to implement that interaction.

Each route element is mapped to one responsible Routable. The Routable needs to be able to present a child, hide a child or replace a child with another child.

Here is the Routable protocol with the methods you should implement:

public protocol Routable {

    func push(
        _ element: RouteElement,
        animated: Bool,
        completion: @escaping RoutingCompletion) -> Routable

    func pop(
        _ element: RouteElement,
        animated: Bool,
        completion: @escaping RoutingCompletion)

    func change(
        _ from: RouteElement,
        to: RouteElement,
        animated: Bool,
        completion: @escaping RoutingCompletion) -> Routable

}

As part of initializing Router you need to pass the first Routable as an argument. That root Routable will be responsible for the first route element.

If e.g. you set the route of your application to ["Home"], your root Routable will be asked to present the view that corresponds to the element "Home".

When working on iOS with UIKit this would mean the Routable would need to set the rootViewController of the application.

Whenever a Routable presents a new route element, it needs to return a new Routable that will be responsible for managing the presented element. If you want to navigate from ["Home"] to ["Home", "Users"] the Routable responsible for the "Home" element will be asked to present the "User" element.

If your navigation stack uses a modal presentation for this transition, the implementation of Routable for the "Home" element might look like this:

func push(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion) -> Routable {

	if element == "User" {
		// 1.) Perform the transition
        userViewController = UIStoryboard(name: "Main", bundle: nil)
            .instantiateViewControllerWithIdentifier("UserViewController") as! Routable

		// 2.) Call the `completion` once the transition is complete
        presentViewController(userViewController, animated: false,
            completion: completion)

		// 3.) Return the Routable for the presented element. For convenience
		// this will often be the UIViewController itself. 
        return userViewController
   	}
   	
   	// ...
}

func pop(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion)

	if element == "Home" {
    	dismissViewControllerAnimated(false, completion: completion)
    }
    
    // ...
}

Calling the Completion Handler within Routables

ReSwiftRouter needs to throttle the navigation actions, since many UI frameworks including UIKit don't allow to perform multiple navigation steps in parallel. Therefor every method of Routable receives a completion handler. The router will not perform any further navigation actions until the completion handler is called.

Changing the Current Route

Currently the only way to change the current application route is by using the SetRouteAction and providing an absolute route. Here's a brief example:

@IBAction func cancelButtonTapped(sender: UIButton) {
    mainStore.dispatch(
        SetRouteAction(["TabBarViewController", StatsViewController.identifier])
    )
}

As development continues, support for changing individual route elements will be added.

Contributing

Compiling & Running tests

ReSwiftRouter uses Carthage for its development dependencies. To build or test any of the targets, run carthage bootstrap.

reswift-router's People

Contributors

ben-g avatar bergquester avatar divinedominion avatar djtech42 avatar frranck avatar hlineholm avatar jayhickey avatar jschmid avatar jzcruiser avatar kmmraj avatar lalemuc avatar lucianopalmeida avatar mokagio avatar obj-p avatar readmecritic avatar richardpfisk avatar rpassis avatar sunshinejr avatar taejoongyoon avatar vood avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reswift-router's Issues

Why my code does not run the protocol method

Why my code does not run the protocol method

    func showMainVC() {
        let mainVC = MainNavigationViewController()
        let nav    = UINavigationController.init(rootViewController: mainVC)
        let leftViewController = LeftMenuViewController()
        let sideMenuController = LGSideMenuController.init(rootViewController: nav, leftViewController: leftViewController, rightViewController: nil)
        sideMenuController.isLeftViewSwipeGestureEnabled    = false
        sideMenuController.leftViewWidth                    = 190;
        sideMenuController.leftViewPresentationStyle        = .slideAbove;
        
        rootViewController = sideMenuController
        router = Router(store: mainStore, rootRoutable: RootRoutable(routable: rootViewController)) { state in
            state.select { $0.navigationState }
        }
        mainStore.dispatch(
            SetRouteAction(["LGSideMenuController", MainNavigationViewController.identifier])
        )
        
        self.window?.rootViewController = sideMenuController
        self.window?.makeKeyAndVisible()

    }

Optimize Travis CI build

It is very wasteful that the 3 different build targets each result in carthage bootstrap building dependencies for all platforms if the binaries cannot be downloaded.

We should consider to at least provide a --platform switch to carthage commands for each platform.

See near the end of the Travis log for the macOS platform:

travis_fold:start:step_start_instance
�[0K�[33;1mStarting instance�[0m
✓ selected image "travis-ci-macos10.13-xcode10-1537303156"
✓ started instance
• sleeping 3s before checking instance start
• polling for instance start completion.....................
• waiting for ssh connectivity...
✓ instance is ready (1m4.455s)
travis_fold:end:step_start_instance
�[0Ktravis_fold:start:step_upload_script
�[0K�[33;1mUploading script�[0m
• waiting for ssh connectivity...
✓ ssh connectivity established (132ms)
✓ uploaded script
✓ uploaded wrapper.sh script
travis_fold:end:step_upload_script
�[0Ktravis_fold:start:worker_info
�[0K�[33;1mWorker information�[0m
hostname: [email protected]
version: v4.1.2 https://github.com/travis-ci/worker/tree/91246b057ccd93649046771f29221f839c19a7d3
instance: 951c2544-9acf-455e-8df2-3af5125d3058 travis-ci-macos10.13-xcode10-1537303156 (via amqp)
startup: 1m4.45529374s
travis_fold:end:worker_info
�[0Knvm is not compatible with the npm config "prefix" option: currently set to "/usr/local"

Run `npm config delete prefix` or `nvm use --delete-prefix v10.10.0 --silent` to unset it.

travis_fold:start:system_info
�[0K�[33;1mBuild system information�[0m

Build language: objective-c

Build id: 437636054

Job id: 437636055

Runtime kernel version: 17.7.0

travis-build version: 972c8c83f

�[34m�[1mBuild image provisioning date and time�[0m

Tue Sep 18 23:03:50 GMT 2018

�[34m�[1mOperating System Details�[0m

ProductName:	Mac OS X

ProductVersion:	10.13.6

BuildVersion:	17G65

�[34m�[1mGit version�[0m

git version 2.19.0

�[34m�[1mbash version�[0m

GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)

Copyright (C) 2007 Free Software Foundation, Inc.

�[34m�[1mGCC version�[0m

Apple LLVM version 10.0.0 (clang-1000.11.45.2)

Target: x86_64-apple-darwin17.7.0

Thread model: posix

InstalledDir: /Applications/Xcode-10.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

�[34m�[1mLLVM version�[0m

Apple LLVM version 10.0.0 (clang-1000.11.45.2)

Target: x86_64-apple-darwin17.7.0

Thread model: posix

InstalledDir: /Applications/Xcode-10.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

�[34m�[1mPre-installed Ruby versions�[0m

ruby-2.3.5

ruby-2.4.3

�[34m�[1mPre-installed Node.js versions�[0m

v10.10.0

v4.9.1

v5.12.0

v6.14.4

v8.12.0

�[34m�[1mmvn -version�[0m

Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T18:33:14Z)

Maven home: /usr/local/Cellar/maven/3.5.4/libexec

Java version: 10.0.2, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-10.0.2.jdk/Contents/Home

Default locale: en_US, platform encoding: UTF-8

OS name: "mac os x", version: "10.13.6", arch: "x86_64", family: "mac"

travis_fold:end:system_info
�[0K

�[32;1mNetwork availability confirmed.�[0m



Fix WWDRCA Certificate

Unable to delete certificate matching "0950B6CD3D2F37EA246A1AAA20DFAADBD6FE1F75"security: AppleWWDRCA.cer: already in /Library/Keychains/System.keychain

$ rvm use

Using /Users/travis/.rvm/gems/ruby-2.4.3



travis_fold:start:git.checkout
�[0Ktravis_time:start:089be948
�[0K$ git clone --depth=50 https://github.com/ReSwift/ReSwift-Router.git ReSwift/ReSwift-Router

Cloning into 'ReSwift/ReSwift-Router'...



travis_time:end:089be948:start=1538747784040844000,finish=1538747785087780000,duration=1046936000
�[0K$ cd ReSwift/ReSwift-Router

travis_time:start:0a483e5e
�[0K$ git fetch origin +refs/pull/100/merge:

From https://github.com/ReSwift/ReSwift-Router

 * branch            refs/pull/100/merge -> FETCH_HEAD



travis_time:end:0a483e5e:start=1538747785152078000,finish=1538747785500294000,duration=348216000
�[0K$ git checkout -qf FETCH_HEAD

travis_fold:end:git.checkout
�[0K

�[33;1mSetting environment variables from repository settings�[0m

$ export GITHUB_ACCESS_TOKEN=[secure]



�[33;1mSetting environment variables from .travis.yml�[0m

$ export LC_CTYPE=en_US.UTF-8

$ export LANG=en_US.UTF-8

$ export FRAMEWORK_NAME="ReSwiftRouter"

$ export UPDATE_DOCS="false"

$ export SCHEME="macOS"

$ export SDK="macosx10.12"

$ export DESTINATION="arch=x86_64"



�[33;1mDisabling Homebrew auto update. If your Homebrew package requires Homebrew DB be up to date, please run `brew update` explicitly.�[0m

$ export HOMEBREW_NO_AUTO_UPDATE=1

travis_fold:start:rvm
�[0Ktravis_time:start:01c334b1
�[0K$ rvm use default

Using /Users/travis/.rvm/gems/ruby-2.4.3



travis_time:end:01c334b1:start=1538747785565629000,finish=1538747787337882000,duration=1772253000
�[0Ktravis_fold:end:rvm
�[0K$ ruby --version

ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-darwin17]

$ rvm --version

rvm 1.29.4 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]

$ bundle --version

Bundler version 1.16.5

travis_fold:start:announce
�[0K$ xcodebuild -version -sdk

iPhoneOS12.0.sdk - iOS 12.0 (iphoneos12.0)

SDKVersion: 12.0

Path: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk

PlatformVersion: 12.0

PlatformPath: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/iPhoneOS.platform

BuildID: A8482458-AB48-11E8-BDA0-0514931EADDD

ProductBuildVersion: 16A366

ProductCopyright: 1983-2018 Apple Inc.

ProductName: iPhone OS

ProductVersion: 12.0



iPhoneSimulator12.0.sdk - Simulator - iOS 12.0 (iphonesimulator12.0)

SDKVersion: 12.0

Path: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.0.sdk

PlatformVersion: 12.0

PlatformPath: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform

BuildID: A8482458-AB48-11E8-BDA0-0514931EADDD

ProductBuildVersion: 16A366

ProductCopyright: 1983-2018 Apple Inc.

ProductName: iPhone OS

ProductVersion: 12.0



MacOSX10.14.sdk - macOS 10.14 (macosx10.14)

SDKVersion: 10.14

Path: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk

PlatformVersion: 1.1

PlatformPath: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/MacOSX.platform

ProductBuildVersion: 18A384

ProductCopyright: 1983-2018 Apple Inc.

ProductName: Mac OS X

ProductUserVisibleVersion: 10.14

ProductVersion: 10.14



AppleTVOS12.0.sdk - tvOS 12.0 (appletvos12.0)

SDKVersion: 12.0

Path: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk

PlatformVersion: 12.0

PlatformPath: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/AppleTVOS.platform

BuildID: 8CB266D2-AB47-11E8-AD6C-B115D1DC00F8

ProductBuildVersion: 16J364

ProductCopyright: 1983-2018 Apple Inc.

ProductName: Apple TVOS

ProductVersion: 12.0



AppleTVSimulator12.0.sdk - Simulator - tvOS 12.0 (appletvsimulator12.0)

SDKVersion: 12.0

Path: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator12.0.sdk

PlatformVersion: 12.0

PlatformPath: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/AppleTVSimulator.platform

BuildID: 8CB266D2-AB47-11E8-AD6C-B115D1DC00F8

ProductBuildVersion: 16J364

ProductCopyright: 1983-2018 Apple Inc.

ProductName: Apple TVOS

ProductVersion: 12.0



WatchOS5.0.sdk - watchOS 5.0 (watchos5.0)

SDKVersion: 5.0

Path: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS5.0.sdk

PlatformVersion: 5.0

PlatformPath: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/WatchOS.platform

BuildID: A011E0F6-AB4A-11E8-A58A-04145DEEDE81

ProductBuildVersion: 16R363

ProductCopyright: 1983-2018 Apple Inc.

ProductName: Watch OS

ProductVersion: 5.0



WatchSimulator5.0.sdk - Simulator - watchOS 5.0 (watchsimulator5.0)

SDKVersion: 5.0

Path: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator5.0.sdk

PlatformVersion: 5.0

PlatformPath: /Applications/Xcode-10.0.app/Contents/Developer/Platforms/WatchSimulator.platform

BuildID: A011E0F6-AB4A-11E8-A58A-04145DEEDE81

ProductBuildVersion: 16R363

ProductCopyright: 1983-2018 Apple Inc.

ProductName: Watch OS

ProductVersion: 5.0



Xcode 10.0

Build version 10A255

$ xcrun simctl list

== Device Types ==

iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)

iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)

iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s)

iPhone 6 (com.apple.CoreSimulator.SimDeviceType.iPhone-6)

iPhone 6 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6-Plus)

iPhone 6s (com.apple.CoreSimulator.SimDeviceType.iPhone-6s)

iPhone 6s Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6s-Plus)

iPhone 7 (com.apple.CoreSimulator.SimDeviceType.iPhone-7)

iPhone 7 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-7-Plus)

iPhone 8 (com.apple.CoreSimulator.SimDeviceType.iPhone-8)

iPhone 8 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-8-Plus)

iPhone SE (com.apple.CoreSimulator.SimDeviceType.iPhone-SE)

iPhone X (com.apple.CoreSimulator.SimDeviceType.iPhone-X)

iPhone XR (com.apple.CoreSimulator.SimDeviceType.iPhone-XR)

iPhone XS (com.apple.CoreSimulator.SimDeviceType.iPhone-XS)

iPhone XS Max (com.apple.CoreSimulator.SimDeviceType.iPhone-XS-Max)

iPad 2 (com.apple.CoreSimulator.SimDeviceType.iPad-2)

iPad Retina (com.apple.CoreSimulator.SimDeviceType.iPad-Retina)

iPad Air (com.apple.CoreSimulator.SimDeviceType.iPad-Air)

iPad Air 2 (com.apple.CoreSimulator.SimDeviceType.iPad-Air-2)

iPad (5th generation) (com.apple.CoreSimulator.SimDeviceType.iPad--5th-generation-)

iPad Pro (9.7-inch) (com.apple.CoreSimulator.SimDeviceType.iPad-Pro--9-7-inch-)

iPad Pro (12.9-inch) (com.apple.CoreSimulator.SimDeviceType.iPad-Pro)

iPad Pro (12.9-inch) (2nd generation) (com.apple.CoreSimulator.SimDeviceType.iPad-Pro--12-9-inch---2nd-generation-)

iPad Pro (10.5-inch) (com.apple.CoreSimulator.SimDeviceType.iPad-Pro--10-5-inch-)

iPad (6th generation) (com.apple.CoreSimulator.SimDeviceType.iPad--6th-generation-)

Apple TV (com.apple.CoreSimulator.SimDeviceType.Apple-TV-1080p)

Apple TV 4K (com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-4K)

Apple TV 4K (at 1080p) (com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-1080p)

Apple Watch - 38mm (com.apple.CoreSimulator.SimDeviceType.Apple-Watch-38mm)

Apple Watch - 42mm (com.apple.CoreSimulator.SimDeviceType.Apple-Watch-42mm)

Apple Watch Series 2 - 38mm (com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-2-38mm)

Apple Watch Series 2 - 42mm (com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-2-42mm)

Apple Watch Series 3 - 38mm (com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-3-38mm)

Apple Watch Series 3 - 42mm (com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-3-42mm)

Apple Watch Series 4 - 40mm (com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-4-40mm)

Apple Watch Series 4 - 44mm (com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-4-44mm)

== Runtimes ==

iOS 8.1 (8.1 - 12B411) - com.apple.CoreSimulator.SimRuntime.iOS-8-1

iOS 8.2 (8.2 - 12D508) - com.apple.CoreSimulator.SimRuntime.iOS-8-2

iOS 8.3 (8.3 - 12F70) - com.apple.CoreSimulator.SimRuntime.iOS-8-3

iOS 8.4 (8.4 - 12H141) - com.apple.CoreSimulator.SimRuntime.iOS-8-4

iOS 9.0 (9.0 - 13A344) - com.apple.CoreSimulator.SimRuntime.iOS-9-0

iOS 9.1 (9.1 - 13B143) - com.apple.CoreSimulator.SimRuntime.iOS-9-1

iOS 9.2 (9.2 - 13C75) - com.apple.CoreSimulator.SimRuntime.iOS-9-2

iOS 9.3 (9.3 - 13E233) - com.apple.CoreSimulator.SimRuntime.iOS-9-3

iOS 10.0 (10.0 - 14A345) - com.apple.CoreSimulator.SimRuntime.iOS-10-0

iOS 10.1 (10.1 - 14B72) - com.apple.CoreSimulator.SimRuntime.iOS-10-1

iOS 10.2 (10.2 - 14C89) - com.apple.CoreSimulator.SimRuntime.iOS-10-2

iOS 10.3 (10.3.1 - 14E8301) - com.apple.CoreSimulator.SimRuntime.iOS-10-3

iOS 11.0 (11.0.1 - 15A8401) - com.apple.CoreSimulator.SimRuntime.iOS-11-0

iOS 11.1 (11.1 - 15B87) - com.apple.CoreSimulator.SimRuntime.iOS-11-1

iOS 11.2 (11.2 - 15C107) - com.apple.CoreSimulator.SimRuntime.iOS-11-2

iOS 11.3 (11.3 - 15E217) - com.apple.CoreSimulator.SimRuntime.iOS-11-3

iOS 11.4 (11.4 - 15F79) - com.apple.CoreSimulator.SimRuntime.iOS-11-4

iOS 12.0 (12.0 - 16A366) - com.apple.CoreSimulator.SimRuntime.iOS-12-0

tvOS 9.0 (9.0 - 13T395) - com.apple.CoreSimulator.SimRuntime.tvOS-9-0

tvOS 9.1 (9.1 - 13U85) - com.apple.CoreSimulator.SimRuntime.tvOS-9-1

tvOS 9.2 (9.2 - 13Y234) - com.apple.CoreSimulator.SimRuntime.tvOS-9-2

tvOS 10.0 (10.0 - 14T328) - com.apple.CoreSimulator.SimRuntime.tvOS-10-0

tvOS 10.1 (10.1 - 14U591) - com.apple.CoreSimulator.SimRuntime.tvOS-10-1

tvOS 10.2 (10.2 - 14W260) - com.apple.CoreSimulator.SimRuntime.tvOS-10-2

tvOS 11.0 (11.0 - 15J380) - com.apple.CoreSimulator.SimRuntime.tvOS-11-0

tvOS 11.1 (11.1 - 15J580) - com.apple.CoreSimulator.SimRuntime.tvOS-11-1

tvOS 11.2 (11.2 - 15K104) - com.apple.CoreSimulator.SimRuntime.tvOS-11-2

tvOS 11.3 (11.3 - 15L211) - com.apple.CoreSimulator.SimRuntime.tvOS-11-3

tvOS 11.4 (11.4 - 15L576) - com.apple.CoreSimulator.SimRuntime.tvOS-11-4

tvOS 12.0 (12.0 - 16J364) - com.apple.CoreSimulator.SimRuntime.tvOS-12-0

watchOS 2.0 (2.0 - 13S343) - com.apple.CoreSimulator.SimRuntime.watchOS-2-0

watchOS 2.1 (2.1 - 13S661) - com.apple.CoreSimulator.SimRuntime.watchOS-2-1

watchOS 2.2 (2.2 - 13V144) - com.apple.CoreSimulator.SimRuntime.watchOS-2-2

watchOS 3.1 (3.1 - 14S471a) - com.apple.CoreSimulator.SimRuntime.watchOS-3-1

watchOS 3.2 (3.2 - 14V243) - com.apple.CoreSimulator.SimRuntime.watchOS-3-2

watchOS 4.0 (4.0 - 15R372) - com.apple.CoreSimulator.SimRuntime.watchOS-4-0

watchOS 4.1 (4.1 - 15R844) - com.apple.CoreSimulator.SimRuntime.watchOS-4-1

watchOS 4.2 (4.2 - 15S100) - com.apple.CoreSimulator.SimRuntime.watchOS-4-2

watchOS 5.0 (5.0 - 16R363) - com.apple.CoreSimulator.SimRuntime.watchOS-5-0

== Devices ==

-- iOS 8.1 --

    iPhone 4s (EFCDF2D8-72E3-43FA-A054-300AF6ACDDA4) (Shutdown)

    iPhone 5 (13ABB1EA-A5AF-493C-8F47-35AE58F2B818) (Shutdown)

    iPhone 5s (511E3648-3BA1-4BBC-B7C5-49E234AF53B3) (Shutdown)

    iPhone 6 (BF136388-A0C8-4E11-8FAD-1E03E3DEA881) (Shutdown)

    iPhone 6 Plus (7F2B939F-658E-4B79-8E33-0981312A162F) (Shutdown)

    iPad 2 (A271359A-61CB-4029-A127-FE6055499AB8) (Shutdown)

    iPad Retina (77DB990C-D3FE-4513-A65F-82E384A4FA67) (Shutdown)

    iPad Air (9E58BE97-1F19-4FDE-BC89-5F35212AAF31) (Shutdown)

-- iOS 8.2 --

    iPhone 4s (A2D44E2C-1E8A-4401-BC9C-C961DC886482) (Shutdown)

    iPhone 5 (BFBF3354-2D6B-475E-9DDD-1F0E5865C22F) (Shutdown)

    iPhone 5s (0CBA275D-7766-4CAA-B4D9-7A466EF242E1) (Shutdown)

    iPhone 6 (C26BF9B1-8269-4BA5-BFB5-663E4677BE41) (Shutdown)

    iPhone 6 Plus (B0F3A903-E772-4733-B4C8-554DD0491D85) (Shutdown)

    iPad 2 (8C1E157C-0C1C-462B-9070-8F7D625CA821) (Shutdown)

    iPad Retina (B6ED532A-76D7-4327-9A47-EFAC6C7A6326) (Shutdown)

    iPad Air (49E90A5F-0789-4F06-B109-8A0B73D902B1) (Shutdown)

-- iOS 8.3 --

    iPhone 4s (588956A1-6D1D-4582-BB07-B7DAAE11D2C4) (Shutdown)

    iPhone 5 (AF69D1C1-73F5-4BD4-832F-F710F4B5183E) (Shutdown)

    iPhone 5s (D9FD4AA3-F9FA-457D-BBAF-5D1DAB7E8B32) (Shutdown)

    iPhone 6 (6A38BF20-4F8D-4622-B239-F913903F9924) (Shutdown)

    iPhone 6 Plus (63DB5D71-E73F-48A2-AA33-BEFF8B86F343) (Shutdown)

    iPad 2 (FC2FDBB9-FC5F-449C-AE5A-C3E9A73F9FA0) (Shutdown)

    iPad Retina (8B43AF5C-D728-4489-8748-F92C263A89BD) (Shutdown)

    iPad Air (11F9C327-AFC0-4882-A606-46095B93337E) (Shutdown)

-- iOS 8.4 --

    iPhone 4s (9F85F879-0850-458D-B67C-94FC716ADE49) (Shutdown)

    iPhone 5 (E57B0296-59DF-4707-BE89-A9D889BD7686) (Shutdown)

    iPhone 5s (B3B7C95B-F60E-439C-B282-1321455A37CB) (Shutdown)

    iPhone 6 (B81EED7C-179B-4CD2-8BE9-FC8B6B102D1A) (Shutdown)

    iPhone 6 Plus (99AD4C4A-E15B-471E-972F-264B448BD8AA) (Shutdown)

    iPad 2 (F10BCF9D-AB0B-466F-A76B-350DD226CE99) (Shutdown)

    iPad Retina (01FA88C5-BB9C-4834-806B-0A20ACCA525B) (Shutdown)

    iPad Air (E62C05EC-90B4-46A9-959E-4BABCA5EBB28) (Shutdown)

-- iOS 9.0 --

    iPhone 4s (03A28FD8-53D1-4F48-9076-BC48F0BA4904) (Shutdown)

    iPhone 5 (387DBF4C-0534-4A95-9948-904FB8F87162) (Shutdown)

    iPhone 5s (3FE8212C-95F7-43C9-B374-AFFD746E1FFA) (Shutdown)

    iPhone 6 (8E0CD5F2-1FE2-4A45-9C46-31918C3E48B7) (Shutdown)

    iPhone 6 Plus (8AE20D0F-03B2-4A0E-8351-E18FF61288E5) (Shutdown)

    iPhone 6s (A16923BD-3B6C-4410-953B-C94DCC3E70D9) (Shutdown)

    iPhone 6s Plus (71657261-6BD2-4B93-818C-66FC1CA23FF6) (Shutdown)

    iPad 2 (4F44BBB0-E74A-43D0-99F3-276097C634EC) (Shutdown)

    iPad Retina (0FBA2A60-3CCE-427A-A647-0D3E16984E27) (Shutdown)

    iPad Air (3D47FA46-1C77-40DD-8CCB-435C5B035D44) (Shutdown)

    iPad Air 2 (5B996E93-BC6E-4D28-B503-A39EF6D13397) (Shutdown)

-- iOS 9.1 --

    iPhone 4s (80D23A33-F9F5-4F16-AB57-D754C480A30B) (Shutdown)

    iPhone 5 (4484DFCC-3347-418F-9FF0-703204B61084) (Shutdown)

    iPhone 5s (1C0725E7-FC29-4967-8D00-CB7FF68C744B) (Shutdown)

    iPhone 6 (B25EC6DB-0B2F-4920-B6C2-8560331BA779) (Shutdown)

    iPhone 6 Plus (094A13F0-4AB9-4ABB-B756-FED4A284BE6C) (Shutdown)

    iPhone 6s (EED17FBD-30A3-4D6B-B197-592A8CA3AA65) (Shutdown)

    iPhone 6s Plus (16381AD7-D303-4C50-B164-CA1427463D04) (Shutdown)

    iPad 2 (64245239-54EC-4E54-94BA-E23F93A0C6B5) (Shutdown)

    iPad Retina (DD04D086-366F-462A-84EA-11A4D8951A24) (Shutdown)

    iPad Air (C2CD5B77-5783-42EC-85FE-5D43BEAB4731) (Shutdown)

    iPad Air 2 (FE5DB178-F2EE-4B4E-A008-82EA9C1026A1) (Shutdown)

    iPad Pro (95F814F6-119E-453B-A3D9-D04D20BAC6BA) (Shutdown)

-- iOS 9.2 --

    iPhone 4s (8DF27340-78C1-4197-B70F-8D8DEA112EEF) (Shutdown)

    iPhone 5 (D28F03FB-136B-4BB3-ACA8-4FD60A1B5E65) (Shutdown)

    iPhone 5s (EBD2C9A4-7AFB-4F3E-83AA-F24824DC4F5C) (Shutdown)

    iPhone 6 (B50B182E-1373-4159-8A83-E0957646BF1A) (Shutdown)

    iPhone 6 Plus (CB1A6235-5DD3-4B55-AD65-D3C2FBFB7075) (Shutdown)

    iPhone 6s (22CBC668-B25C-4EE3-AA14-404571A46DCB) (Shutdown)

    iPhone 6s Plus (655A21FD-92EE-4222-9543-8612EBD200CB) (Shutdown)

    iPad 2 (5091BF3C-AD49-4AE6-ACE5-F1511AE28C17) (Shutdown)

    iPad Retina (54F3089E-E04E-40E4-812B-C7EE5035EFEA) (Shutdown)

    iPad Air (782A97D9-8F1F-4207-A939-3DA28E2D0D9A) (Shutdown)

    iPad Air 2 (880836C3-4E26-4362-B5DD-ED9820FB51A8) (Shutdown)

    iPad Pro (91D0F851-B56E-49B4-BD5C-63370A3D6FB6) (Shutdown)

-- iOS 9.3 --

    iPhone 4s (9259396B-CC4F-4D48-A0F8-55D745F5DC17) (Shutdown)

    iPhone 5 (671252CA-8074-429D-A987-CA337BBC278C) (Shutdown)

    iPhone 5s (3A4C0FF6-C565-4245-9BC5-2458777DE550) (Shutdown)

    iPhone 6 (070794B4-9D06-4197-B536-78925DFB7430) (Shutdown)

    iPhone 6 Plus (F283F140-E5EF-4EB7-B9EA-4C1F338DC621) (Shutdown)

    iPhone 6s (B8BAD605-2A09-4413-9206-976A9825A77C) (Shutdown)

    iPhone 6s Plus (00955D63-1307-42C9-AC5D-A08E2CA579D0) (Shutdown)

    iPad 2 (1E4CC51F-2EBF-4805-8E7C-7AE1993697CC) (Shutdown)

    iPad Retina (120A696B-9C41-4871-932C-D2EA428960BC) (Shutdown)

    iPad Air (7F4996C2-71CD-4558-8F2C-B9FAFA871FCB) (Shutdown)

    iPad Air 2 (A8979160-C4E8-47AF-BD4A-7DA985D8A181) (Shutdown)

    iPad Pro (0DD66FF2-5527-4FF6-8020-AC34C14C93BD) (Shutdown)

-- iOS 10.0 --

    iPhone 5 (E590FE16-7B7E-4114-B060-97A5A7A9183C) (Shutdown)

    iPhone 5s (9B57A4D8-F6ED-436D-A416-459A4D0CEBCE) (Shutdown)

    iPhone 6 (37B43FFA-E3EF-4C25-B824-956D8A173820) (Shutdown)

    iPhone 6 Plus (088134B4-F162-464C-ABC2-C635B1EB5699) (Shutdown)

    iPhone 6s (41AB6594-8762-4691-B73F-A45329E507B4) (Shutdown)

    iPhone 6s Plus (56FC34C5-DAF1-4433-B2EB-0958770A07D3) (Shutdown)

    iPhone SE (E1385ECA-3B3B-42DE-AAA7-34E32DC556D1) (Shutdown)

    iPad Air (1A64A800-D9F1-4961-81A6-66F5EC7E3CF8) (Shutdown)

    iPad Air 2 (98B24290-DE19-4509-B783-384B4B0488AE) (Shutdown)

    iPad Pro (9.7 inch) (3EAA34E3-3825-4434-9058-8972290F65DA) (Shutdown)

    iPad Pro (12.9 inch) (5BE7DF21-A9E7-418F-BC10-92764C821F7A) (Shutdown)

-- iOS 10.1 --

    iPhone 5 (37C72363-2FF0-492B-8326-69F88530064F) (Shutdown)

    iPhone 5s (52B05089-A901-4652-BA4E-B397F609DD33) (Shutdown)

    iPhone 6 (813599B2-51C1-42EA-A49F-9272AFB9FF45) (Shutdown)

    iPhone 6 Plus (78770E31-D04C-402A-8269-68EB2EA3B8DD) (Shutdown)

    iPhone 6s (A7E2C591-BDEE-401F-B434-40A294F135FF) (Shutdown)

    iPhone 6s Plus (CF12C5F3-F7E0-4856-A22E-B0357DEC0267) (Shutdown)

    iPhone 7 (58B2D865-681F-402E-9297-119328D831F1) (Shutdown)

    iPhone 7 Plus (FCD373ED-4707-446E-9E61-9970F45603BA) (Shutdown)

    iPhone SE (B2773D91-996E-4888-B8FC-5DDD0938FAE3) (Shutdown)

    iPad Air (280DF2A4-FFE6-4EB9-A51A-D4B326854601) (Shutdown)

    iPad Air 2 (927354E9-D1C4-4978-A27D-0B89174C459E) (Shutdown)

    iPad Pro (9.7 inch) (8947E887-B635-4004-84A0-6F40F9DAF59C) (Shutdown)

    iPad Pro (12.9 inch) (98CBA1E5-571F-4CBB-ADA9-1300D2ECF304) (Shutdown)

-- iOS 10.2 --

    iPhone 5 (A46CD317-3AEE-4388-9607-CC93866CB9FE) (Shutdown)

    iPhone 5s (42DC2A97-286F-41AE-A0D3-617C219DB343) (Shutdown)

    iPhone 6 (A8426239-8A23-49B6-AAA7-7A33793AD972) (Shutdown)

    iPhone 6 Plus (885AF654-8885-412B-8174-5CBB7E8E1840) (Shutdown)

    iPhone 6s (FAD21FF0-8530-4333-B65B-A0AF24BD831A) (Shutdown)

    iPhone 6s Plus (86D37563-84BC-42CF-A381-57D7F546A151) (Shutdown)

    iPhone 7 (7297E6DF-2A9B-48CE-821D-AA966BB64E18) (Shutdown)

    iPhone 7 Plus (E756D8FB-6636-4F54-8685-735CC0E87CE6) (Shutdown)

    iPhone SE (BF1F56F4-4C90-4981-84A0-9826CBE2D7B9) (Shutdown)

    iPad Air (B80C3B66-9959-456A-A153-5741647C4274) (Shutdown)

    iPad Air 2 (19A09CC0-40B9-40D8-810B-745CC5C1DC0D) (Shutdown)

    iPad Pro (9.7 inch) (18076D56-5C73-463B-B7DB-BEC2B66E78E9) (Shutdown)

    iPad Pro (12.9 inch) (D27A8B64-AD95-48AC-A13C-BA7EC120D07C) (Shutdown)

-- iOS 10.3 --

    iPhone 5 (BECF8755-9249-47E3-B215-95A359E25178) (Shutdown)

    iPhone 5s (15200B6B-D419-43CC-8B0C-83E0E433A41C) (Shutdown)

    iPhone 6 (7ED8A401-4174-49F7-9339-7F57C229BA5B) (Shutdown)

    iPhone 6 Plus (7166A23D-B7A9-4B07-8248-3D1BA0EFCE2D) (Shutdown)

    iPhone 6s (5944B615-5A68-48A3-B2FC-83FD1346523D) (Shutdown)

    iPhone 6s Plus (A82950B2-84A3-4379-A1FE-56D3F71F4F93) (Shutdown)

    iPhone 7 (7A8EC105-EBA7-44B6-86BC-BDEEE4737F27) (Shutdown)

    iPhone 7 Plus (FC11E32A-EABF-4BDD-9908-6F71FF424356) (Shutdown)

    iPhone SE (A6EC77B6-560E-421E-8963-63E770365E1C) (Shutdown)

    iPad Air (619B6BFB-A716-4CFA-8D49-7745D710DC47) (Shutdown)

    iPad Air 2 (C926B761-ED61-41EE-AACF-FEA8128B1345) (Shutdown)

    iPad (5th generation) (9920923A-0C6F-48F5-B765-595F936A33C2) (Shutdown)

    iPad Pro (9.7 inch) (C8615F06-841C-4629-984A-591E590026A8) (Shutdown)

    iPad Pro (12.9 inch) (23C9D412-01BD-4C78-A210-7F4D4DA2F3E1) (Shutdown)

    iPad Pro (12.9-inch) (2nd generation) (4A2FDD1A-FEA3-4D62-9B76-3AF4B1B1391C) (Shutdown)

    iPad Pro (10.5-inch) (F89831E8-D32C-4B8F-90ED-BA1D67FFB170) (Shutdown)

-- iOS 11.0 --

    iPhone 5s (31ADD3B5-55CC-453B-898C-B3C5D23A1653) (Shutdown)

    iPhone 6 (6D11D0A7-5EF0-4062-BC61-8A7AB27D6065) (Shutdown)

    iPhone 6 Plus (21D554EF-8715-4724-B859-8074563373AB) (Shutdown)

    iPhone 6s (47944C1A-37A8-48A8-A965-206D9D96D4B8) (Shutdown)

    iPhone 6s Plus (029FA527-318A-469C-BB0E-C26F2CE9DA55) (Shutdown)

    iPhone 7 (1EB48D44-E632-4C3B-AED8-D42F3D6DDE83) (Shutdown)

    iPhone 7 Plus (CCDD727E-393F-48C5-A24C-125DE72D15E6) (Shutdown)

    iPhone 8 (4046F182-6A43-4A5A-BAE4-D0FB95BFBBFD) (Shutdown)

    iPhone 8 Plus (A8D66B1A-B642-403C-9E48-9D09C8082891) (Shutdown)

    iPhone SE (FC99C044-000B-45F8-84EF-738CB82A0BA2) (Shutdown)

    iPhone X (95B0C42E-4A51-424C-8995-55B7823B2FB8) (Shutdown)

    iPad Air (0097B359-2591-45B9-AFDB-4A887A62AB0A) (Shutdown)

    iPad Air 2 (D5C5C29D-7F4D-4D96-848F-BBDF3F7BAB37) (Shutdown)

    iPad (5th generation) (489105A0-53C9-471D-A7BA-12C11D5F482C) (Shutdown)

    iPad Pro (9.7-inch) (2F99EC8A-02D8-4299-9D62-B1D0FB731E11) (Shutdown)

    iPad Pro (12.9-inch) (739F3B8B-656C-4AD9-8652-8C1655CE0FEF) (Shutdown)

    iPad Pro (12.9-inch) (2nd generation) (F5628977-0396-4AD4-B6D5-41E413AEF0C7) (Shutdown)

    iPad Pro (10.5-inch) (09EBDFDE-F984-4817-B666-06094E593996) (Shutdown)

-- iOS 11.1 --

    iPhone 5s (A56955E0-9FB7-4B37-92C1-3B696CEA393D) (Shutdown)

    iPhone 6 (3184C892-D0C6-4C94-9D60-C2CF88994FB5) (Shutdown)

    iPhone 6 Plus (FFB8DD7D-4A5E-4369-870F-0CD581A5D6AF) (Shutdown)

    iPhone 6s (56A07293-5434-4795-B39B-24FB6EB9E63F) (Shutdown)

    iPhone 6s Plus (23C73129-36C2-493E-896D-2480531F6709) (Shutdown)

    iPhone 7 (F1224BDB-41A6-4EEF-8C2B-F63EE9468061) (Shutdown)

    iPhone 7 Plus (9B32D1B6-9E1D-4056-B59E-40CF6B0460D1) (Shutdown)

    iPhone 8 (74075926-5A4C-4A04-BAD4-8EC0D0C1D5AC) (Shutdown)

    iPhone 8 Plus (44807A12-A076-4565-9231-BFFD38678A86) (Shutdown)

    iPhone SE (982C8A66-F5F4-4A94-BB7F-39F30E68268E) (Shutdown)

    iPhone X (6738BF46-574B-4E9D-BF3D-B0A9706711A9) (Shutdown)

    iPad Air (F84F230B-C931-4B18-8A6D-7C3FF8C8D079) (Shutdown)

    iPad Air 2 (462D04F3-4274-4792-AEC2-061B04E80EA0) (Shutdown)

    iPad (5th generation) (07AB58D5-9401-4E64-AE04-5979AD7170C7) (Shutdown)

    iPad Pro (9.7-inch) (1B244D80-917D-409B-858B-96E89C2A5A12) (Shutdown)

    iPad Pro (12.9-inch) (5AFEB06A-3A3F-4368-AF95-C7C6D12ECDEB) (Shutdown)

    iPad Pro (12.9-inch) (2nd generation) (667FAF50-C0F6-4553-9F9E-735044BEF76E) (Shutdown)

    iPad Pro (10.5-inch) (023AC128-65B2-424D-8B95-5A7E8812D811) (Shutdown)

-- iOS 11.2 --

    iPhone 5s (0BF3A5EB-CEA7-4CC7-903A-5CCA6E4EA372) (Shutdown)

    iPhone 6 (FF1324B7-61ED-4791-B5D7-4F796A391FCB) (Shutdown)

    iPhone 6 Plus (C3E1603A-861E-4A77-B842-70906DE4E549) (Shutdown)

    iPhone 6s (E84F2271-17AA-4867-895B-5B3A9B3D6438) (Shutdown)

    iPhone 6s Plus (7864EAAF-3AF6-4EDF-AB3D-A68F73696E82) (Shutdown)

    iPhone 7 (583913B9-C4A0-4C4F-8CC7-9E094FCE9FEC) (Shutdown)

    iPhone 7 Plus (97853327-B821-443B-B77A-A5424596843B) (Shutdown)

    iPhone 8 (CC3B13E0-D5E5-4739-B97C-6397C77B7468) (Shutdown)

    iPhone 8 Plus (5CDA8B8E-66EB-4148-A033-397BE80EDF2F) (Shutdown)

    iPhone SE (AD35CF5E-8134-4F1B-9D03-C0D21304392A) (Shutdown)

    iPhone X (B2EE5F31-970D-4554-8613-1889FE3C99FB) (Shutdown)

    iPad Air (50A608D8-1E0C-4C9E-A58E-993F7867B143) (Shutdown)

    iPad Air 2 (EC3277FB-43D4-4187-91E0-2D3BDA808386) (Shutdown)

    iPad (5th generation) (BAB0582E-4576-4299-8460-D82F2B361FC7) (Shutdown)

    iPad Pro (9.7-inch) (D0102F63-5472-45AC-A632-3C341922AF51) (Shutdown)

    iPad Pro (12.9-inch) (B78C7685-40A8-4170-A1EC-A6929F949D29) (Shutdown)

    iPad Pro (12.9-inch) (2nd generation) (275CAF6A-727D-4ADF-A1C8-C674B1FB44CA) (Shutdown)

    iPad Pro (10.5-inch) (43E07A12-5BAB-4DA6-AF4F-48EAC6D26F8A) (Shutdown)

-- iOS 11.3 --

    iPhone 5s (400FA61D-390D-4790-BED7-72AE67309386) (Shutdown)

    iPhone 6 (B4B0C794-B4A8-427E-AD57-B3C72B466D95) (Shutdown)

    iPhone 6 Plus (F3B1A366-19F0-4ED5-B2BB-B75D997D2AA5) (Shutdown)

    iPhone 6s (88A0F834-5F02-4825-BCF0-4CDB342252E3) (Shutdown)

    iPhone 6s Plus (A1BB73C1-FE09-4E6D-979C-FC2F0AA847C0) (Shutdown)

    iPhone 7 (C9CC3690-DA33-470F-9BB0-40080EA93CBC) (Shutdown)

    iPhone 7 Plus (C044A175-B555-4205-A452-647B828A6A38) (Shutdown)

    iPhone 8 (5A44E517-2473-41A9-BDB4-D5CA9EB1291B) (Shutdown)

    iPhone 8 Plus (D2B108C3-BE4F-4E32-81C2-E124948BED01) (Shutdown)

    iPhone SE (285977C8-443F-4A38-9243-0823C2784CD1) (Shutdown)

    iPhone X (15765ED3-9D83-43FD-883F-C29238E05915) (Shutdown)

    iPad Air (233141FE-5B4F-40F9-ADF6-58C1ABDBF0A1) (Shutdown)

    iPad Air 2 (BD23F712-2601-442F-9704-F1E40CD691C4) (Shutdown)

    iPad (5th generation) (48459591-BE0E-40F0-9C76-BCE3B3C33378) (Shutdown)

    iPad Pro (9.7-inch) (AEA2AEC8-2403-4E7D-B7AD-E2B26272F0A5) (Shutdown)

    iPad Pro (12.9-inch) (EC95721B-0E76-49CC-BD75-3C15E7B9C369) (Shutdown)

    iPad Pro (12.9-inch) (2nd generation) (023A0772-B0E2-4EDE-869D-E50C85089EC3) (Shutdown)

    iPad Pro (10.5-inch) (CAB1167C-C291-491D-9E84-0BB5CAFE0F6E) (Shutdown)

-- iOS 11.4 --

    iPhone 5s (9F915A81-8103-4E2D-8580-28AE0FAFF9D3) (Shutdown)

    iPhone 6 (B40D6C98-15B8-4107-AC09-DE1B40C421F3) (Shutdown)

    iPhone 6 Plus (6D16DD82-F0CA-4E39-8318-FBD1534C534D) (Shutdown)

    iPhone 6s (B0004E74-65CC-41BF-9B26-608E46D1911C) (Shutdown)

    iPhone 6s Plus (65FC92EB-5DEA-4CAD-BD21-676398429184) (Shutdown)

    iPhone 7 (F3AF5B83-E56C-44F3-BC38-9C2DECD7A8FA) (Shutdown)

    iPhone 7 Plus (EF5F0B56-5FA8-4928-985E-8E74623E00E5) (Shutdown)

    iPhone 8 (24BC6B8C-40F5-44F9-99F8-D22E3A8A133C) (Shutdown)

    iPhone 8 Plus (2DE6C3B7-B324-4FBD-8E78-DE5584512597) (Shutdown)

    iPhone SE (06C2F801-541F-44D2-AD5D-A32B71E17741) (Shutdown)

    iPhone X (486263E5-2B26-4F96-8CFA-847B788C62AD) (Shutdown)

    iPad Air (F65C1777-DFD8-42E3-B056-F9CF17D78661) (Shutdown)

    iPad Air 2 (21D18E53-BF15-471C-B384-BC8C87B99BA1) (Shutdown)

    iPad (5th generation) (68A1A02F-4AF8-4C34-88F1-6491E4FFAF46) (Shutdown)

    iPad Pro (9.7-inch) (52190323-F563-4508-92B2-7DA8A1991F0F) (Shutdown)

    iPad Pro (12.9-inch) (BB33DBEA-95D7-4C36-B8C5-403A83D18524) (Shutdown)

    iPad Pro (12.9-inch) (2nd generation) (14906BED-C238-4782-93D9-32EDA0DE3486) (Shutdown)

    iPad Pro (10.5-inch) (588B09FA-F394-4484-A042-BB37C7E1BE64) (Shutdown)

-- iOS 12.0 --

    iPhone 5s (729AD353-0594-4EC6-8724-AA634F082C46) (Shutdown)

    iPhone 6 (A03D6B49-C912-43CD-90FF-1D0EBAF61710) (Shutdown)

    iPhone 6 Plus (3EA006CD-4B86-421F-AECC-F2A14B539F73) (Shutdown)

    iPhone 6s (0A1E3E09-AAA3-4C9A-913E-AF0B552F10F8) (Shutdown)

    iPhone 6s Plus (51529A35-D482-49A4-9A52-AAA87E1B3A5D) (Shutdown)

    iPhone 7 (0691E97D-FA40-4B74-9301-867A9DDC4956) (Shutdown)

    iPhone 7 Plus (4E4DE1E1-05A3-4D78-B83D-8F2339A380A7) (Shutdown)

    iPhone 8 (905CBD11-AE5D-4118-B38B-6286FC0EEE24) (Shutdown)

    iPhone 8 Plus (6E3FB755-3401-4888-8630-23D174C67160) (Shutdown)

    iPhone SE (76F004D5-C34C-45A2-BA12-AA2F589F394F) (Shutdown)

    iPhone X (12BA173C-33E7-4FE2-8839-EC760B7288E6) (Shutdown)

    iPhone XR (C6D47361-0601-4891-9D4A-B90F53CEE29E) (Shutdown)

    iPhone XS (56EC15B5-8406-4B57-88EC-C31F279ED9EE) (Shutdown)

    iPhone XS Max (E5486005-1831-4DBE-B151-B54F00F798C9) (Shutdown)

    iPad Air (78E9F25B-E2A4-4913-8693-D2AB450CBB7B) (Shutdown)

    iPad Air 2 (BD56667F-A9C8-4A4F-ACFD-45990514D081) (Shutdown)

    iPad (5th generation) (5DE1565B-1F4E-445E-9A5E-1467EA1E7E35) (Shutdown)

    iPad Pro (9.7-inch) (3C709BAB-5646-46D6-BA52-E0FFA1EF4F63) (Shutdown)

    iPad Pro (12.9-inch) (BA75C999-F24D-4459-8703-8E031D737A95) (Shutdown)

    iPad Pro (12.9-inch) (2nd generation) (31A638E2-D95D-4CCE-A012-CDB9D81682C4) (Shutdown)

    iPad Pro (10.5-inch) (6C561E42-2D4B-42C8-96F5-FB70A81ED2D4) (Shutdown)

    iPad (6th generation) (EA78AB5F-AC96-4811-88FD-750E761546F1) (Shutdown)

-- tvOS 9.0 --

    Apple TV 1080p (3C1FE4C7-68F1-44B3-8053-C89ECE711CA5) (Shutdown)

-- tvOS 9.1 --

    Apple TV 1080p (2F4F1118-D72A-4E1C-A26C-7F63821B23F9) (Shutdown)

-- tvOS 9.2 --

    Apple TV 1080p (9A78889A-AC99-47EC-933D-8D9305BDC0E9) (Shutdown)

-- tvOS 10.0 --

    Apple TV 1080p (DCAB8046-F5DB-4115-84C6-94D35D5E679D) (Shutdown)

-- tvOS 10.1 --

    Apple TV 1080p (D08506AF-E744-434F-90E1-2FB7FAA3F320) (Shutdown)

-- tvOS 10.2 --

    Apple TV 1080p (FD58AAFC-454A-4741-8633-888E70026335) (Shutdown)

-- tvOS 11.0 --

    Apple TV (023F836E-A79B-46F2-A6F1-DA5174933BC3) (Shutdown)

    Apple TV 4K (74656552-5137-431C-B4A3-871C4B5562BC) (Shutdown)

    Apple TV 4K (at 1080p) (BA4B026C-2731-4F3A-9671-A22E14769262) (Shutdown)

-- tvOS 11.1 --

    Apple TV (C966015C-0E79-490F-871A-DCC8116CB601) (Shutdown)

    Apple TV 4K (8FE750EA-7AD1-460E-A6FD-98E4B8183B86) (Shutdown)

    Apple TV 4K (at 1080p) (B6557234-884D-40E7-BA81-00F040D00A84) (Shutdown)

-- tvOS 11.2 --

    Apple TV (14C83BC7-4FFF-4980-856C-DAB239228B82) (Shutdown)

    Apple TV 4K (E508234C-A542-4493-9894-84AC8AB01EA6) (Shutdown)

    Apple TV 4K (at 1080p) (8537CACE-2D8F-40E8-A217-9A8E3D24E05A) (Shutdown)

-- tvOS 11.3 --

    Apple TV (86248501-E674-4D65-9968-AB380AED465F) (Shutdown)

    Apple TV 4K (F0487378-2B08-4BBB-BC30-55C1759BD24D) (Shutdown)

    Apple TV 4K (at 1080p) (4C1EC3FF-5360-40EA-950C-91A435CB4923) (Shutdown)

-- tvOS 11.4 --

    Apple TV (2E99E1F9-0642-4E95-BE9E-6915F5A5246E) (Shutdown)

    Apple TV 4K (9C57A52F-9A6B-4541-B746-6B8DDE32073F) (Shutdown)

    Apple TV 4K (at 1080p) (DF4C6149-488A-4320-A901-55CDF79BB4B8) (Shutdown)

-- tvOS 12.0 --

    Apple TV (9183152D-F5DD-40CF-929B-1A926BE1BD25) (Shutdown)

    Apple TV 4K (E68B4CB8-6E25-4011-9617-2A5243312DAD) (Shutdown)

    Apple TV 4K (at 1080p) (D1462B83-8678-412F-8177-0E90EF2182E1) (Shutdown)

-- watchOS 2.0 --

    Apple Watch - 38mm (52B9C33D-5B9A-4074-977F-0D0D2086E997) (Shutdown)

    Apple Watch - 42mm (C5A23F4A-497F-4C47-86BD-1A16ED7798BC) (Shutdown)

-- watchOS 2.1 --

    Apple Watch - 38mm (D27512B8-51F5-4042-8C03-3D3EB436C892) (Shutdown)

    Apple Watch - 42mm (BCBE0484-4ED6-4074-B72E-8F70AA21EA3D) (Shutdown)

-- watchOS 2.2 --

    Apple Watch - 38mm (8E6C9B65-1099-415F-909A-77F88D4C7A1A) (Shutdown)

    Apple Watch - 42mm (F8791868-2938-46FF-B6D8-A6F103D42710) (Shutdown)

-- watchOS 3.1 --

    Apple Watch - 38mm (CA0964B3-A5F5-4FF9-96DF-A8F30A95DA7D) (Shutdown)

    Apple Watch - 42mm (4849390B-9BF9-47F3-B816-73BDA2DAB58C) (Shutdown)

    Apple Watch Series 2 - 38mm (018D7781-9232-4D56-9FC1-FD726460AF5D) (Shutdown)

    Apple Watch Series 2 - 42mm (928F9CC2-0CE9-4551-9543-5FDA27CA26BB) (Shutdown)

-- watchOS 3.2 --

    Apple Watch - 38mm (5F12BAEA-BF6D-446C-B626-9C701F3BD806) (Shutdown)

    Apple Watch - 42mm (89D8E4B6-099A-4F02-820B-B0D28BB721B3) (Shutdown)

    Apple Watch Series 2 - 38mm (B4942C6F-5C06-43AF-BDA3-87F6865F8E4D) (Shutdown)

    Apple Watch Series 2 - 42mm (477B5C9A-6A48-4830-A54B-57DB1BB769E6) (Shutdown)

-- watchOS 4.0 --

    Apple Watch - 38mm (4F8603E2-4F66-47CE-A56D-2CB0758B6E3E) (Shutdown)

    Apple Watch - 42mm (FA9B4F79-435D-408B-9753-EB3C68B9B696) (Shutdown)

    Apple Watch Series 2 - 38mm (F56B676F-219C-4814-9472-3EC301FB0B56) (Shutdown)

    Apple Watch Series 2 - 42mm (F3F3E4CB-FD4A-410D-ACF3-BA9892533378) (Shutdown)

    Apple Watch Series 3 - 38mm (C02902A9-2B01-445E-A277-6C5D6F0B80F1) (Shutdown)

    Apple Watch Series 3 - 42mm (7E3974DE-86EB-499A-B25D-01DF3D49CFF6) (Shutdown)

-- watchOS 4.1 --

    Apple Watch - 38mm (7783F230-EBFA-4B0F-A446-6F4D652E9C30) (Shutdown)

    Apple Watch - 42mm (BEF42A23-074F-4CDE-9B79-76971F5C0D2D) (Shutdown)

    Apple Watch Series 2 - 38mm (34AFED10-4A06-4A10-A446-52F9F09BDA80) (Shutdown)

    Apple Watch Series 2 - 42mm (EC96E340-AC16-4A78-A167-067DFA65F90F) (Shutdown)

    Apple Watch Series 3 - 38mm (E239BBB5-30BA-4AC1-B46D-E1A76E371E16) (Shutdown)

    Apple Watch Series 3 - 42mm (7D4A1A9C-191A-4B1D-B7B0-E31924C5321E) (Shutdown)

-- watchOS 4.2 --

    Apple Watch - 38mm (40693B0F-EBD8-407E-AFD5-960B005A61EF) (Shutdown)

    Apple Watch - 42mm (4F0EE993-E329-4F0B-87FA-8BAC2024DD1A) (Shutdown)

    Apple Watch Series 2 - 38mm (C836783F-2B7A-45A7-89FF-858442FB3E93) (Shutdown)

    Apple Watch Series 2 - 42mm (B437C722-66D4-41A7-8C92-91A64DDA6A24) (Shutdown)

    Apple Watch Series 3 - 38mm (9BB0FA5B-05DB-433E-A15F-FE84DE652178) (Shutdown)

    Apple Watch Series 3 - 42mm (E9461727-7B77-4B44-910C-A95120E4161C) (Shutdown)

-- watchOS 5.0 --

    Apple Watch Series 2 - 38mm (4A9C7604-7B37-43F1-9D38-CBE16F7E2F79) (Shutdown)

    Apple Watch Series 2 - 42mm (F5CE7E24-9E36-4780-90BC-CEADA337C536) (Shutdown)

    Apple Watch Series 3 - 38mm (FB846112-086E-4334-9821-FC9E1CF41163) (Shutdown)

    Apple Watch Series 3 - 42mm (205D0EB3-94DE-4A1B-8621-0D1E995537FF) (Shutdown)

    Apple Watch Series 4 - 40mm (4B608CF6-DD5C-43B8-A4A0-860B69894E54) (Shutdown)

    Apple Watch Series 4 - 44mm (8A919ED7-8DC5-49A5-A019-8872AC59F058) (Shutdown)

== Device Pairs ==

101637C2-16FE-4F72-A049-095B2C5BE615 (active, disconnected)

    Watch: Apple Watch Series 4 - 40mm (4B608CF6-DD5C-43B8-A4A0-860B69894E54) (Shutdown)

    Phone: iPhone XS (56EC15B5-8406-4B57-88EC-C31F279ED9EE) (Shutdown)

A9960FF2-92DB-4DCD-8C38-FC261C38EEED (active, disconnected)

    Watch: Apple Watch Series 4 - 44mm (8A919ED7-8DC5-49A5-A019-8872AC59F058) (Shutdown)

    Phone: iPhone XS Max (E5486005-1831-4DBE-B151-B54F00F798C9) (Shutdown)

travis_fold:end:announce
�[0Ktravis_fold:start:before_install
�[0Ktravis_time:start:2422d27c
�[0K$ carthage bootstrap

*** Checking out Nimble at "v7.3.1"

*** Checking out Quick at "v1.3.2"

*** Checking out ReSwift at "4.0.1"

*** Cloning Nimble

*** Cloning Quick

*** Cloning ReSwift

*** xcodebuild output can be found in /var/folders/nz/vv4_9tw56nv9k3tkvyszvwg80000gn/T/carthage-xcodebuild.H14zYg.log

*** Skipped downloading ReSwift.framework binary due to the error:

	"Bad credentials"

*** Skipped downloading Quick.framework binary due to the error:

	"Bad credentials"

*** Skipped downloading Nimble.framework binary due to the error:

	"Bad credentials"

*** Building scheme "Nimble-tvOS" in Nimble.xcodeproj

*** Building scheme "Nimble-iOS" in Nimble.xcodeproj

*** Building scheme "Nimble-macOS" in Nimble.xcodeproj

*** Building scheme "Quick-macOS" in Quick.xcworkspace


Route with parameters

When I use SwiftFlowRouter in a real-ish app, I figure I'd need to send parameters with route. For instance "/users/123" or "/posts/2345/comments"

I could use route ["Users:123"], ["Posts:2345", "Comments"] to represent them, but the swift way to do them is probably instead of string, use a StateType where have a name and parameter state as route?

I have also see subRouteState field, but I have no idea what it is and what it does.

[Request | Suggestion] Protocol extension hides compiler errors

I was trying to implement the router on an app and it kept crashing with the error that I wasn't implementing the Routable methods which I had or I thought I had.

The signature was wrong on my implementation and thanks to this extension https://github.com/ReSwift/ReSwift-Router/blob/master/ReSwiftRouter/Routable.swift#L31-L55

The compiler couldn't tell me that was the case because the extension was already providing conformance to the protocol.

Wouldn't it make more sense to remove said extension and let the compiler complain about the lack of conformance to that protocol so newcomers can adopt it more easily?

Maybe there's a bigger issue behind the reasoning of adding this default conformance and I just don't know about it but from my experience having the compiler complain about the wrong signature would have made this easier to track 😄

Question: Simulate detail segue animation

Hey everybody,

I'm working on an app in which we have many situations of master-detail flow, if we were using Storyboard segues we would use the Detail Segue.

let detail: UIViewController = UIStoryboard(name: "Storyboard", bundle: nil).instantiateViewController(withIdentifier: Storyboard.identifier)

viewController.present(detail, animated: true, completion: completionHandler)

return detail as! Routable

Given this code that we're using right now, how could we simulate the same animation as the DetailSegue one? (new viewController slides left to be on top of old viewController)

We tried looking into the default animations provided by Apple but they're flashy and not what we're looking for, also we're aware there's a work around by creating an interactive transition, but we were wondering if there's something more straightforward than that.

Thank you! Great job on ReSwift and ReSwiftRouter 😉

Multiple routes with same identifier question

I'm in the process of setting up ReSwiftRouter in an app and am running into a problem with some of the routes when popping them off and making sure that the completion handler is appropriately called.

So I start on the route [Foo, Bar] and from there I want to go to the route [Foo, Bar, Bar]. The push to the second Bar view controller is fine though I'm running into problems when I pop off the Bar route.

In the BarRouter I've setup push and pop functions with the code required, and by placing in breakpoints I can see that the push function is called for BarRouter though the pop function isn't.

This unfortunately results in a weird state whereby the completion handlers aren't called.

Any help in addressing this would be greatly appreciated.

ReSwiftRouterStuck, even when calling completionHandler()

I've called the usual completionHandler() function after implementing a route just like any other; however, every time I try to navigate to this route, it's still triggering ReSwiftRouterStuck. Are there any known situations where completionHandler is invalid for some reason or other cases that cause a "stuck" state?

SetRouteAction break separation of concerns

Requiring every view controller to know the whole application hierarchy breaks the separation of concerns. I am going to try to find a simple example to show what I mean. Again, this is heavily related to #3 and #4.

Say you are in the state (where each letter is a controller):

A -> B -> C

And C wants to show something that is its child. It's easy for it to add a new controller to the list:

A -> B -> C -> D

But now if C wants to show something that is out of its scope, like:

A -> E -> F

C should only be able to send an Action saying "I want to show F", without having to know about the whole "breadcrumb" to get there.

I could create and action called ShowF and having a reducer that knows how to create the correct Route. However, this reducer will be forbidden to dispatch SetRouteAction since it is already inside a dispatch action of ShowF.

Does this make sense?

Can I pass any data with SetRouteAction?

With ReSwift StandardAction I can pass some arbitrary payload. Looks like I can't do it with the help of SetRouteAction, because it only takes an array of RouteElementIdentifiers which are, unfortunately, strings.
I think there's an opportunity for major overhaul, because routes for parametrized controllers are effectually impossible. Also string route identifiers stink.

Initializing routes not working

I have an issue where the extension with the fatal error is being called instead of my custom procol conforming classes. I probably haven't set everything up right... here's the relevant code - also not that this is a macOS app but that shouldn't matter...

let store = Store<AppState> (
  reducer: AppReducer(),
  state: nil
)

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {


  //let appState: AppState
  let router: Router<AppState>
  override init() {
    //self.appState = AppState(realmState: nil, navigationState: NavigationState())
    router = Router(store: store, rootRoutable: MainWindowRouter()) { state in
      state.navigationState
    }
    store.dispatch(
      SetRouteAction([Window.EditorWindow.rawValue])
    )
    super.init()
  }

  func applicationDidFinishLaunching(aNotification: NSNotification) {
    // Insert code here to initialize your application

  }

  func applicationWillTerminate(aNotification: NSNotification) {
    // Insert code here to tear down your application
  }

  @IBAction func openPreferences(sender: AnyObject) {
    store.dispatch(
      SetRouteAction([Window.Preferences.rawValue])
    )
  }
}
struct AppState: StateType {

  let realmState: RealmState?
  let navigationState: NavigationState

  init (realmState: RealmState?, navigationState: NavigationState) {
    self.realmState = realmState
    self.navigationState = navigationState
  }
}

class MainWindowRouter: Routable {

// I've set breakpoints, and none of these get called
  func changeRouteSegment(from: RouteElementIdentifier,
                          to: RouteElementIdentifier,
                          completionHandler: RoutingCompletionHandler) -> Routable {

    completionHandler()
    return self

  }

  func pushRouteSegment(routeElementIdentifier: RouteElementIdentifier,
                        completionHandler: RoutingCompletionHandler) -> Routable {
    if routeElementIdentifier == "EditorWindow" {
      let mainWindow = NSStoryboard(name: "Main", bundle: nil).instantiateInitialController() as! Routable
      completionHandler()
      return mainWindow
    }
    return self
  }

  func popRouteSegment(routeElementIdentifier: RouteElementIdentifier,
                       completionHandler: RoutingCompletionHandler) {
    completionHandler()
    if routeElementIdentifier == "EditorWindow" {

    }
  }
}

Am I missing something? The tests don't appear to be doing anything else, and I've scoured the documentation!

Why does popRouteSegment(_,_,_) is called on presentING routable, not presentED?

I've presented modally vc2 on vc1 from vc1 like this: SetRouteAction(["VC1id", "VC2id"]). On vc1 routable pushRouteSegment(_,_,_) is being called correctly.
Then, when I call SetRouteAction(["VC1id"]) the popRouteSegment(_,_,_) is being called on vc1 routable, keeping me from calling vc2.dismiss(_,_) because I don't have link to vc2 there.
What do I do incorrectly, or is it an expected behaviour?

Routing actions for a (deep) navigation stack

Not sure if this is covered elsewhere but I couldn't find it anywhere in the documentation.

Supposed I have a navigation stack of:

UINavController -> VC1 -> VC2 -> VC3

From my VC1 I can dispatch SetRouteAction(["VC1", "VC2"]... to push VC2 into the stack and make it current.

What is the correct way to go about pushing VC3? I can dispatch SetRouteAction(["VC1", "VC2", "VC3"]...) but this will obviously not scale too well, and it will prevent me from reusing view controllers in different "stack" arrangements.

My ideal solution would be to simply dispatch SetRouteAction(["VC2", "VC3"]...) but this triggers a changeRouteSegment instead of a pushRouteSegment.

Have I missed something obvious?
Many thanks,
Rog

handle route globally

My understanding of NavigationState.route is that each of its RouteElementIdentifier elements corresponds to a Routable that is triggered. So if my route state goes from ["home"] to ["home", "favorites"] than the root Routable will push FavoritesVC (for example). So each successive RouteElementIdentifier that is appended during a SetRouteAction([] hands control off to a new Routable.

But what if I want to push a loading screen as the 3rd Routable. A loading screen could be presented from any VC. Is there a way to define the routing to a loading screen (say by presenting LoadingVC modally) once and have FavoritesVC inherit the ability? Because a ProfileVC along with 10 other VC's would reasonably present a loading screen.

Router initialization v0.6.0

I'm struggling with router initialization for days and I think the documentation is out dated. Can anyone help me and explain how the following code should be and what are those protocols in the closure ?

router = Router(store: mainStore, rootRoutable: RootRoutable(routable: rootViewController)) { state in 
	state.navigationState
}

Running tests / Contributing readme

I'm having trouble getting the project to compile to run tests.
I've tried doing carthage bootstrap, but that fails with some watchOS target issues.
I've tried doing carthage bootstrap --platform ios, which seems to delete the ReSwift.xcodeproj folder which it seems like the project is depending on.
Restoring that folder still doesn't work, as I'm unable to get ReSwift itself to compile its framework.

It would be beneficial to add a "Contributing" section to the readme which includes instructions on how to get the tests running.

How to dimiss a modal navigation stack with a new Route

Imagine a navigation controller which gets presented and contains multiple viewcontrollers, which are pushed because of a Route constructed out of Route identifiers with respect to some user navigation flow, e.g. the route might be; [root, nav, vcA, vcB, vcC].
Popping one viewcontroller is achieved by dispatching a SetRouteAction, with for example a new route, e.g. [root, nav, vcA, vcB].
This works fine, but if for example the user wants to dismiss the presented viewcontroller, the route should be for this example; [root].
However doing so, will just pop (animated) each viewcontroller and then dismiss the presented viewcontroller.
What will be a good way to get the presented viewcontroller dismissed in one time with a route action? I was thinking of using the SpecificRouteData option... but maybe it is better to just dismiss the presented viewcontroller and then update the route path..
any ideas?

Routing Multiple Displayed Paths

This is more of a prompt to discussion, and possibly something to document for users, as this is likely a very common use case.

How would one propose this router could work if the application has multiple displayed paths? (IE a split-screen application, master/detail, sidebar controller with some internal navigation?)

I see two possibilities (I'm sure there are many more) -- One which may work within the current codebase, and one which would require refactoring.

Multiple navigationState

I've noticed that protocol HasNavigationState isn't actually used anywhere, so perhaps the naming of the navigation state is less relevant? Could one have multiple navigation states? ie masterState and detailState, Building a tree of some kind when a given route/controller has two visible children?
I could see extending SetRouteAction such that there is a SetMasterRouteAction and SetDetailRouteAction etc when it splits.

This seems like it could be done within the current codebase -- I'll have to test it and see

struct State: StateType {
    var rootState: NavigationState
    var masterState: NavigationState
    var detailState: NavigationState
}

store.dispatch(SetRootRouteAction([masterDetailContainerRoute]))
store.dispatch(SetMasterRouteAction([documentRoute]))
store.dispatch(SetDetailRouteAction([marginEditorRoute]))

we'd then have three routers involved, one for each NavigationState, and the AppReducer would pass the correct navigationState to NavigationReducer.handleAction depending on the action.

Route as Tree instead of Array

Alternatively, one could represent the current route as a recursive tree instead of an array:

indirect enum Route {
    case Node(RouteElementIdentifier, [Route])
}

While this would be more much work to write out and understand initially, it maintains a single navigationState. An example single navigation structure could look like

SetRouteAction(.Node(firstRoute, [
    .Node(secondRoute, [
        .Node(thirdRoute, [])
        ])
    ]))

and a nested master/detail would be the following:

SetRouteAction(.Node(mainRoute, [
    .Node(masterRoute, [
        .Node(documentRoute, [])
        ]),
    .Node(detailRoute, [
        .Node(marginEditorRoute, [])
        ]),
    ]))

Another downside to this choice is it provides no compile time hinting as to how many children can exist, whereas the first option its immediately obvious, because there are X navigation states. (However, the current implementation provides no compile time hinting as to what routes exist, nor how they can be mixed together, only runtime errors)

Animate transition between view controllers

Hi,
I am currently trying to refctor my app from MVVM to ReSwift. One of the things that i adopt is the ReSwiftRouter. The router allows me to navigate from one screen to another (either by push view controller into a navigation controller or by present it modally) .

I also consider to use Hero for animate transition between view controllers.
Hero created some extension to UIViewController which allows you to send a view controller there and animationType and then it will automatically animate the transition between both view controllers.
Now I wanted to know where is the best place to add this transition code? What i did now is to add it to the routable via the following lines of code:

` Hero.shared.setDefaultAnimationForNextTransition(.zoom)
Hero.shared.setContainerColorForNextTransition(.lightGray)

    let navigationController = UINavigationController.init(rootViewController: viewController)
    self.viewController.hero_replaceViewController(with: navigationController)
    
    return SignUpRoute(viewController)`

I am not sure that this is the best place or not to put the code.

What i was thinking is maybe to write an extension to Routable that will receive the source view controller and the destination view controller and animation type and this function will execute the animation.

Wanted to know what do you think or maybe there is a better solution?

Thanks.

How to use the Router with navigationcontrollers

Somehow it confuses me how to setup a router with navigationcontrollers involved. For example, when the first viewcontroller is a navigationcontroller defined in some storyboard, the root viewcontroller for that navigation controller is actually a route segment deeper… so does that mean it would be better not to use the segue connection between the navigationcontroller and its root viewcontroller? For the app I try to add ReSwift, I have multiple storyboard flows with navigationcontrollers.

dispatch_release not called on semaphore.

I noticed that dispatch_release is never called on the semaphore. According to Apple's docs:

When your application no longer needs the semaphore, it should call dispatch_release to release its reference to the semaphore object and ultimately free its memory."

I would put it in myself with a pull request, but I'm not entirely sure where it should go.

Philosphy behind choosing whether to pop or change a segment

Let's say I have two different routes that are different lengths that descend from the same parent node:

[ "foo", "bar1", "baz" ]
[ "foo", "bar2" ]

And I have four different Routable objects:

  1. foo
  2. bar1
  3. bar2
  4. baz

where "foo" is the parent Routable of "bar1" and "bar2", and "baz" is a child routable of "bar1".

When I make the transition between the two routes, it would make sense to me that "bar1" would be sent a pop-action to remove "baz", but why should "foo" also be sent a pop-action to remove "bar1" and then be sent a separate push-action to add back "bar2"? Since they share the same common parent in "foo", shouldn't "foo" get sent a change-action to exchange "bar1" with "bar2"?

Right now the behavior defining this is from the following rule:

  1. The old route had an element after the commonSubroute and the new route does not we need to pop the route segment after the commonSubroute

And it means that everything descending from "foo", because the routes are different lengths, is first popped off and then pushed back on, rather than popping off the non-common elements but doing a change-action for the most senior child element that is not in the common subroute.

Is this default behavior something that should possibly be modified?

Cannot implement Routable

It seems that the protocol extensions for Xcode to swallow the your class doesn't conform to the Routable protocol.

Usage with deep-linking and animations

We are currently looking for a way to better handle our view controllers history, and Swift Flow Router happens to be a nice way to do it. As it's in early development, I'd like to give my 2 cents about one thing that seems to be important.

When re-working the way we handle our view controllers history/state, we also want to add support for deep linking, or what Apple calls universal links.

Recreating a NavigationState from a URL in application(_:continueUserActivity:restorationHandler:) can be easily done. This is tightly related to #3.

However, implementing Routable becomes harder. If your view controllers present many children view controllers with animations (presenting a modal, pushing a controller in UINavigationController, ...) and you want to recreate the whole UI, it will take a few seconds and the user will see each view controller being presented one after the other.

Also, if you are in the state:

A -> B -> C

And going to

A -> B

You will want to have an animation. However if you go to

A -> D

You will certainly not want the animation from C to B then from B to A then from A to D.

The implementation in Routable should be able to know if the pushed/poped child view controller should be animated or not.

Any thought on that?

SetRouteAction 'route' is inaccessible due to 'internal' protection level in tests

I'm trying to write some tests where I check that that my ActionCreator has successfully created and dispatched a SetRouteAction on my dispatcher.

I'd like to be able to read the route that was passed in to the SetRouteAction, however I'm unable to read it. It would be nice if the SetRouteAction had a public getter on the route (and perhaps even the animated member).

Building the project with carthage update fails

When I am cloning the project and want to build the dependencies using carthage update, the call fails with the following info:

*** Fetching Quick
*** Fetching Nimble
Failed to check out repository into /Users/nburk/Library/Caches/org.carthage.CarthageKit/dependencies/Quick: No object named "swift-3.0" exists

I also opened an issue in the carthage repo, as I'm not sure if that's an issue with carthage or this repository. Does anyone else have the same problem when running carthage update?

Fail to support swift3 or xcode8

Hi

I updated to xcode8 and Swift3 . We use
pod 'ReSwift'
pod 'ReSwiftRouter'
When we want to implement StoreSubscriber in our ViewController. It started giving weird errors.

i have uploaded some errors i'm getting. Please give me syntax for subscribing to store and unsubscribing in swift3

My Code:
store.subscribe(self) { state in
(state.momentState, state.feedState)
}

store.unsubscribe(self)

var store = Store(reducer: AppReducer() as AnyReducer, state: nil, middleware: [loggingMiddleware])

error2
error1

@Ben-G @askielboe @agentk @garnett

Setting a Route without Triggering the Router

In some cases, when UIKit performs a transition that we cannot force through the router, we need to notify the router about the change (also discussed in #17).

In such cases we might want to update the route, without triggering the actual routing. If the transition already happened directly from within UIKit we don't want to trigger another action in the router.

We'll need to add this to the API of the router in form of a new action. Maybe we could call it NotifyOfNewRoute(route).

Release ReSwift Router

For a new project I decided to use ReSwift, so I was wondering if the ReSwiftRouter lib has any changes of importance on the roadmap before it will get a release tag in Git (for Swift 3 support)..?
And if not recommended, what is a good alternative navigation architecture with ReSwift?

Carthage v0.6.0 does not compile

Having Carthage throwing the following error:

*** Checking out ReSwiftRouter at "0.6.0"
*** xcodebuild output can be found in /var/folders/ns/0h9r9v5908x4x67v5j9wvhvw0000gn/T/carthage-xcodebuild.yzuJSO.log
*** Building scheme "ReSwiftRouter-iOS" in ReSwiftRouter.xcodeproj
Build Failed
	Task failed with exit code 65:
	/usr/bin/xcrun xcodebuild -project /Users/marbetschar/Development/Valletti/App/Valletti/Carthage/Checkouts/ReSwiftRouter/ReSwiftRouter.xcodeproj -scheme ReSwiftRouter-iOS -configuration Release -derivedDataPath /Users/marbetschar/Library/Caches/org.carthage.CarthageKit/DerivedData/9.1_9B55/ReSwiftRouter/0.6.0 -sdk iphoneos ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES archive -archivePath ./ SKIP_INSTALL=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=NO CLANG_ENABLE_CODE_COVERAGE=NO (launched in /Users/marbetschar/Development/Valletti/App/Valletti/Carthage/Checkouts/ReSwiftRouter)

This usually indicates that project itself failed to compile. Please check the xcodebuild log for more details: /var/folders/ns/0h9r9v5908x4x67v5j9wvhvw0000gn/T/carthage-xcodebuild.yzuJSO.log

New Release for ReSwift 4.0 and Deployment Target set to 8.0

ReSwiftRouter is still maintained right?

Would be nice to perform the following minor update:

  • new release(0.6.0) so that carthage default uses ReSwiftRouter updated for ReSwift 4.0
  • change the deployment target or ReSwiftRouter(master) to 8.0

Point of changeRouteSegment method in Routable?

Hi,

When should you use func changeRouteSegment(from: RouteElementIdentifier, to: RouteElementIdentifier, completionHandler: RoutingCompletionHandler) -> Routable, and how do you implement it at all?

Thanks!

Cannot convert 'MainStore<AppState>' to expected 'MainStore<_>'

I'm having some trouble getting the Router instantiated. It seems to complain about my mainStore object regardless of if I'm using MainStore or RecordingMainStore, and I'm having trouble tracking down where it's choking.

Here's the error:
Cannot convert value of type 'MainStore<AppState>' to expected argument type 'MainStore<_>'

And here's the relevant AppDelegate.swift code:

import ReSwift
import ReSwiftRouter
import ReSwiftRecorder

var mainStore = MainStore(reducer: AppReducer(), state: AppState())
//var mainStore: RecordingMainStore<AppState> = RecordingMainStore(reducer: AppReducer(), appState: AppState())

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var router: Router<AppState>!
    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.

        let initialController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()

        router = Router(store: mainStore, rootRoutable: AppRoutable(root: initialController))

With the error presenting itself on that last line.

Thank you for the help.

When debugging sometimes getting, fatal error: [SwiftFlowRouter]:

When debugging and hitting breakpoints during active route changes, sometimes I get the following fatal error:

fatal error: [SwiftFlowRouter]: Router is stuck waiting for a completion handler to be called. Ensure that you have called the completion handler in each Routable element.

import ReSwiftRouter requires deployment target iOS 9.1

when use import ReSwiftRouter, it gives error

Module file's minimum deployment target is ios9.1 v9.1:

Carthage/Build/iOS/ReSwiftRouter.framework/Modules/ReSwiftRouter.swiftmodule/i386.swiftmodule

Is there anyway to lower it to iOS 8 or make deployment target insensitive?

Thanks

Is it have a demo project ?

I'm a beginner of Reswift. The ReSwift-Router README is equivocal for me, In particular, the RootRoutable . I don't know how to use ReSwift-Router in my project . Could you show me a demo for usage? Thanks!

SwiftPM Support?

I use SwiftPM to manage my dependencies. Is there a plan to support SwiftPM?

Question: Interactive Transition?

Does this router support interactive transitions?
Successfully presenting the next view controller always works of course, but is there a way to handle cancelling the transition so the router won't think it's made it to the next routable when it really has not?

Fails to build with Carthage

It seems ReSwift Router fails to build properly through Carthage given an empty directory with the following Cartfile:

github "ReSwift/ReSwift" ~> 1.0
github "ReSwift/ReSwift-Router"

Here's the build output (ignore the Swift 2.2 warnings):

$ carthage update --platform ios
*** Fetching ReSwift-Router
*** Fetching ReSwift
*** Checking out ReSwift at "1.0.0"
*** Checking out ReSwift-Router at "0.2.6"
*** Fetching Swift-Flow
*** xcodebuild output can be found in /var/folders/mn/xfk73_v56ns232tl5s448zdm0000gn/T/carthage-xcodebuild.6HC7Uc.log
*** Building scheme "ReSwift-iOS" in ReSwift.xcodeproj
*** Building scheme "ReSwiftRouter-iOS" in ReSwiftRouter.xcodeproj
** BUILD FAILED **


The following build commands failed:
    CompileSwift normal arm64 /Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift
    CompileSwift normal arm64 /Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationState.swift
    CompileSwift normal arm64 /Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/Router.swift
    CompileSwift normal arm64 /Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationActions.swift
    CompileSwift normal arm64 /Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/Routable.swift
    CompileSwiftSources normal arm64 com.apple.xcode.tools.swift.compiler
(6 failures)
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:34:26: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:42:9: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:9:8: error: no such module 'ReSwift'
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:34:26: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:42:9: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:9:8: error: no such module 'ReSwift'
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:34:26: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:42:9: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:9:8: error: no such module 'ReSwift'
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:34:26: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:42:9: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:9:8: error: no such module 'ReSwift'
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:34:26: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:42:9: warning: 'var' parameters are deprecated and will be removed in Swift 3
/Users/rpowell/Code/ReSwiftBugs/Carthage/Checkouts/ReSwift-Router/ReSwiftRouter/NavigationReducer.swift:9:8: error: no such module 'ReSwift'
A shell task failed with exit code 65:
** BUILD FAILED **

subscribe signature doesn't match

in Router.swift the store's invoked with self and a selector argument.. this isn't declared in Store. is this a specific branch or something? thank you.
screen shot 2017-04-11 at 8 49 15 pm

Help with SetRouteSpecificData

I tried to play around with the new feature: SetRouteSpecificData , but somehow I can't get it working.
Basically when replacing a working SetRouteAction with SetRouteSpecificData, the route change is not performed...

so for example:

store.dispatch(SetRouteAction(["root", "login", "dialog"]))

is working just fine, but:

store.dispatch(SetRouteSpecificData(route: ["root", "login", "dialog"], data: error))

not.

Did I miss something?

`assertionFailure()` as opposed to `fatalError()`

Hello,

In my own fork of this project, I've gone ahead to remove all references to fatalError() in my use of the Router. This warranted a change to the router itself, to prevent any operations from occurring if I ever return nil from the pushRouteSegment or changeRouteSegment functions. I have manually popped the route from the stack if we ever hit newState() with an invalid route.

Is this the correct way to do this? I would like some further clarification too on why fatalError() was chosen as opposed to assertionFailure() which would be evaluated in DEBUG builds only. The situation we faced was the occasional (widespread) crash in the Routables in our release builds which was horrendously detrimental to our user experience.

I am happy to make a pull request for this too. Otherwise a discussion would be great! 🙌

Routing with UITabBarController scenario

UITabBarController allow to have multiple navigation stacks in each tabs. For example :

tabbar

On the previous image we can see tat we have 4 different stacks at the same time :

  • A / Y /
  • B / X /
  • C /
  • D /

The NavigationState design is :

public struct NavigationState {
    public init()
    public var route: Route
    public var routeSpecificState: [ReSwiftRouter.RouteHash : Any]
}

I'm struggling to find a way to use the current implementation while maintaining the native behaviour of the UITabBarController. The idea is to have the following scenario to work properly

Sequence NavigationState.route Next user action
1 / Tab on A in tab bar
2 / A Tap on Y in A
3 / A / Y Tab on B in tab bar
4 / B Tap on A in tab bar
5 / A / Y

Given the current implementation, NavigationState.route in the 5th sequence would be / A instead of / A / Y because the user action in the 4th sequence is destructive.

It seems that we should support non-linear navigation. Maybe more something like a route tree along with the current route in that tree.

Question: How do you implement deeplinks with ReSwift-Router?

I've read through the ReadMe and a lot of the issues here. From what I've seen, some have experienced difficulties using this Router for specific issues like a Tab Bar Controller or when trying to pass data along with a Route change.

I'm at the beginning of a project and trying to look ahead. Would the implementation of deeplinks require much modification of the codebase? Is there an approach you suggest?
@Ben-G

Use with UIPageViewController

Hi,
I am trying to think what is the best way to use the Router with UIPageViewController. What i did so far is create a routable which receive the some hostViewController instance and then add UIPageViewController into it. Now in order to page from one page to another the host controller must confirm the UIPageController datasource. the page controller datasource must return the number of pages to display and also the view controller for any page. Based on those things i wanted to ask what is the best way to achieve it?

Thanks.

Intercept Back Button Call in UINavigationController?

Problem: When using ReSwiftRouter we want every view controller change to be reflected by a route update. This means we need to be notified when UIKit's container view controllers trigger VCs to be presented or hidden.

For UITabBarController we can implement delegate methods to intercept view controller changes and allow the router to change view controllers instead of the controller handling the changes directly.

For the back button of UINavigationController there's no comparable solution. Right now I'm using a workaround that I'm not very happy with: https://github.com/ReSwift/GitHubBrowserExample/blob/master/SwiftFlowGitHubBrowser/ViewControllers/RepositoryDetailViewController.swift#L37-L41

When a VC disappears, I check if the current route is still the one of the current VC. If that's the case, we know that the VC was dismissed without the route being updated; in response I update the route manually.

Any suggestions on how to intercept back button taps more directly are welcome. Ideally this would not involve replacing bar button items, or any other larger modifications of the UINavigationController.

StandardActionConvertible

Use of undeclared type 'StandardActionConvertible' in NavigationAction.swift

  • Xcode: 8.3.3
  • Swift 3.1
  • iOS 10

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.