Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/SpectralDragon/LiteRoute

LiteRoute is easy transition for your app. Written on Swift 4
https://github.com/SpectralDragon/LiteRoute

easy-to-use framework ios router routing routing-protocols swift swift-framework viper-architecture

Last synced: 4 days ago
JSON representation

LiteRoute is easy transition for your app. Written on Swift 4

Awesome Lists containing this project

README

        

# LiteRoute
[![Build Status](https://travis-ci.org/SpectralDragon/LiteRoute.svg?branch=master)](https://travis-ci.org/SpectralDragon/LiteRoute)
[![Pod version](https://img.shields.io/cocoapods/v/LiteRoute.svg)](https://img.shields.io/cocoapods/v/LiteRoute.svg)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
![Platform](https://img.shields.io/badge/platform-iOS-lightgrey.svg)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/SpectralDragon/LiteRoute/blob/master/LICENSE.txt)
[![Twitter](https://img.shields.io/badge/twitter-@SpectralDragon_-blue.svg?style=flat)](http://twitter.com/spectraldragon_)
![Swift](https://img.shields.io/badge/Swift-4.2-green.svg)

## Description
LiteRoute is easy transition between VIPER modules, who implemented on pure Swift.
We can transition between your modules very easy from couple lines of codes.

### What's happend with LightRoute?

Because CocoaPods Dev Team doesn't respond me about return right to my lib, I will move `LightRoute` to other name `LiteRoute`.
Code and all rights saved.

## Installation
### CocoaPods

Add to your podfile:

```ruby
pod "LiteRoute"
```

### Carthage

[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with [Homebrew](http://brew.sh/) using the following command:

```bash
$ brew update
$ brew install carthage
```

To integrate LiteRoute into your Xcode project using Carthage, specify it in your `Cartfile`:

```ogdl
github "SpectralDragon/LiteRoute" ~> 2.1
```

Run `carthage update` to build the framework and drag the built `LiteRoute.framework` into your Xcode project.

### Swift Package Manager

Once you have your Swift package set up, adding LiteRoute as a dependency is as easy as adding it to the dependencies value of your `Package.swift`.

**Swift 4**

```swift
dependencies: [
.package(url: "https://github.com/SpectralDragon/LiteRoute.git", from: "2.1")
]
```

## Example

- **New Demo project:** [iOS Example](https://github.com/SpectralDragon/LiteRoute/tree/master/Example)
- Old Demo project: [Viper-LightRoute-Swinject](https://github.com/SpectralDragon/Viper-LightRoute-Swinject)

## About LiteRoute

LiteRoute can work with `Segue`, `UINavigationController` and default view controller presenting.

For all transition, returns `TransitionNode` instance, who managed current transition. You can change transition flow, how you want.

## How to use

For example, we will make the transition between the two VIPER modules:

```swift
import LiteRoute

// MARK: - The module initiating the transition.

protocol FirstViperRouterInput: class {
func openModule(userIdentifier: String)
}

final class FirstViperRouter: FirstViperRouterInput {

// This property contain protocol protected view controller for transition.
weak var transitionHandler: TransitionHandler!

// View controller identifier for current storyboard.
let viewControllerIdentifier = "SecondViperViewController"

func openModule(userIdentifier: String) {

try? transitionHandler

// Initiates the opening of a new view controller.
.forCurrentStoryboard(resterationId: viewControllerIdentifier, to: SecondViperViewControllerModuleInput.self)

// Set animate for transition.
.transition(animate: false)

// Set transition case.
.to(preffered: TransitionStyle.navigation(style: .push))

// View controller init block.
.then { moduleInput in
moduleInput.configure(with: userIdentifier)
}
}
}

// MARK: - The module at which the jump occurs.

// Module input protocol for initialize
protocol SecondViperViewControllerModuleInput: class {
func configure(with userIdentifier: String)
}

final class SecondViperPresenter: SecondViperViewControllerModuleInput, ... {

// Implementation protocol
func configure(with userIdentifier: String) {
print("User identifier", userIdentifier) // Print it!
// Initialize code..
}

}
```
In this case, you make default transition between viewControllers and configure moduleInput how you want.
But also, you can use just viewController, example:

```swift
.forCurrentStoryboard(resterationId: viewControllerIdentifier, to: SecondViperPresenter.self)
/// and etc..
```

**Noteโ—๏ธ**
`moduleInput` - by default that property contain your `output` property in destination view controller. You can change that use methods `selector:`.
You can use next for get custom moduleInput:
- by string: `selector(_ selector: String)`
- by selector: `selector(_ selector: Selector)`
- by keyPath: `selector(_ selector: KeyPath)`

## Transition case
For example we analyze this code, then contain two case for work with transition:

**First case:**

This default case, with default LiteRoute implementation. If you want just present new module, then use that:

```swift

try? transitionHandler

// Initiates the opening of a new view controller.
.forCurrentStoryboard(resterationId: viewControllerIdentifier, to: SecondViperViewControllerModuleInput.self)

// Setup module input.
.then { moduleInput in
moduleInput.configure(with: "Hello!")
}

```

**Second case:**

But first way can't be flexible, for that has `customTransition()` method. This method returns `CustomTransitionNode`. This node not support default `TransitionNode` methods.
`CustomTransitionNode` is class, who return method flexible settings your transition, but for this transition flow, you should be implement your transition logic, and call `them(_:)` or `perform()` method for activate transition.

Example:

```swift

try? transitionHandler

// Initiates the opening of a new view controller.
.forCurrentStoryboard(resterationId: viewControllerIdentifier, to: SecondViperViewControllerModuleInput.self)

// Activate custom transition.
.customTransition()

// Custom transition case.
.transition { source, destination in
// Implement here your transition logic, like that:
// source.present(destination, animated: true, completion: nil)
}

// Setup module input.
.then { moduleInput in
moduleInput.configure(with: "Hello custom transition!")
}

```

## Customize transition

For customize your transition you can change transition presentation and set animation.

**Animate transition**

This methods can animate your current transition.

```swift
.transition(animate: false)
```

**Change presentation**

Method `to(preffered:)`, have responsobility for change presentation style. He work with UINavigationController, UISplitViewController, ModalPresentation and default presentation.

```swift
.to(preferred: TransitionStyle)
```
**๐Ÿ“ŒSupported styles:**
- ***Navigation style*** (`push`, `pop`, `present`)
```swift
.to(preferred: .navigation(style: NavigationStyle))
```
- ***Split style*** (`detail`, `default`)
```swift
.to(preferred: .split(style: SplitStyle))
```
- ***Modal style*** (`UIModalTransitionStyle`, `UIModalPresentationStyle` - standart UIKit's presentations styles.)
```swift
.to(preferred: .modal(style: style: (transition: UIModalTransitionStyle, presentation: UIModalPresentationStyle)))
```

**Configure you destination controller**

Sometimes you need add additional dependency in your controller. For this case, will be add method `apply(to:)`. That method return destination controller and you can configurate him.

````swift

try? transitionHandler
.forSegue(identifier: "LiteRouteSegue", to: SecondViperViewControllerModuleInput.self)
.apply(to: { controller in
// configure your controller.
})
.then { moduleInput in
// configure your module
}

````

## Transition on new storyboard

Also LiteRoute can transition on new storyboard instance like this:

```swift

// We remeber this class :)
func openModule(userIdentifier: String) {

let storyboard = UIStoryboard(name: "NewStoryboard", bundle: Bundle.main)
let factory = StoryboardFactory(storyboard: storyboard)

try? transitionHandler

// Initiates the opening of a new view controller from custom `UIStoryboard`.
.forStoryboard(factory: factory, to: SecondViperViewControllerModuleInput.self)

// Set animate for transition.
.transition(animate: false)

// View controller init block.
.then { moduleInput in
moduleInput.configure(with: userIdentifier)
} // If you don't want initialize view controller, we should be use `.perform()`
}

```

## Transition for Segue

You can initiate transition from `UIStoryboardSegue` like this:

```swift

func openModule(userIdentifier: String) {
try? transitionHandler
// Performs transition from segue and cast to need type
.forSegue(identifier: "LiteRouteSegue", to: SecondViperViewControllerModuleInput.self)
.then { moduleInput in
moduleInput.setup(text: "Segue transition!")
}
}

```

If you want to use `EmbedSegue`, need to add segue in storyboard, set class `EmbedSegue` and source view controller must conform protocol `ViewContainerForEmbedSegue` like this:

```swift

extension SourceViewController: ViewContainerForEmbedSegue {
func containerViewForSegue(_ identifier: String) -> UIView {
return embedView
}
}

```

And you can initiate `EmbedSegue` transition like this:

```swift

func addEmbedModule() {
try? transitionHandler
.forSegue(identifier: "LiteRouteEmbedSegue", to: EmbedModuleInput.self)
.perform()
}

```

## Close current module

If you want initiate close current module, you should be use:

```swift
.closeCurrentModule()
```

And after this you can use `perform()` method for initiate close method.

**Animate close transition**

This methods can animate your current transition.

```swift
.transition(animate: false)
```

Note: Default `true`

**Custom close style**

If you wanna close pop controller or use popToRoot controller, you must perform method `preferred(style:)`.
That method have different styles for your close transition.

If you need call `popToViewController(:animated)` for your custom controller, you must perform method `find(pop:)`.

````swift
try? transitionHandler
.closeCurrentModule()
.find(pop: { controller -> Bool
return controller is MyCustomController
})
.preferred(style: .navigation(style: .findedPop))
.perform()
````

## Support UIViewControllerTransitioningDelegate

LiteRoute 2.0 start support UIViewControllerTransitioningDelegate for your transition. We can work with that use next methods:

```swift
.add(transitioningDelegate: UIViewControllerTransitioningDelegate)
```

## Note

- Mastermind: [ViperMcFlurry](https://github.com/rambler-digital-solutions/ViperMcFlurry)
- License: `MIT`
- Author: Vladislav Prusakov / [email protected]

Thanks for watching.