Latest | 1.3.2 |
---|---|
Homepage | https://github.com/iKrisLiu/Navigator |
License | MIT |
Platforms | ios 10.0 |
Authors |
Navigator
Navigator is a generic navigation framework for view controllers. It can decouple the dependency of different modules/components/view controllers.
Features
- Data passing between view controllers bidirectional, inject data provider implementation for mocking data.
- Navigation between view controllers with system default or custom transition animation
- Support deep link and universal link
- Goto any navigator
Architecture
Installation
Carthage
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate Navigator into your Xcode project using Carthage, specify it in your Cartfile
:
github "iKrisLiu/Navigator" ~> 1.0
CocoaPods
CocoaPods is a dependency manager for Cocoa projects. To integrate Navigator into your Xcode project using CocoaPods, specify it in your Podfile
:
pod 'SmartNavigator', '~> 1.0'
Swift Package Manager
Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift
compiler. To integrate Navigator into your Xcode project, specify it in your Package.swift
.
dependencies: [
.package(url: "https://github.com/iKrisLiu/Navigator", from: "1.0.0")
]
Usage
Initialize Root View Controller
NavigatonControler
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Decoupling Way: Recommend to use this way among modules
// View controller class name (The swift class name should be "ModuleName.ClassName")
let main = DataModel(vcName: "ModuleName.ViewController", navName: "UINavigationController", mode: .reset)
// Coupling Way: Recommend to use this way inside one module
let main = DataModel(vcClass: ViewController.self, navClass: UINavigationController.self, mode: .reset)
// If present view controller without passing any `UINavigationController`, use it as default one.
Navigator.defaultNavigationControllerClass = UINavigationController.self
Navigator.root.window = window
Navigator.root.show(main)
return true
}
SplitViewControler
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let master = DataModel(vcClass: MasterViewController.self, navClass: UINavigationController.self)
let detail = DataModel(vcClass: DetailViewController.self, navClass: UINavigationController.self)
let split = DataModel(vcClass: SplitViewController.self, children: [master, detail])
Navigator.root.window = window
Navigator.root.show(split)
return true
}
TabBarControler
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let firstTab = DataModel(vcClass: TabItemViewController.self, navClass: UINavigationController.self)
let master = DataModel(vcClass: MasterViewController.self, navClass: UINavigationController.self)
let detail = DataModel(vcClass: DetailViewController.self, navClass: UINavigationController.self)
let secondTab = DataModel(vcClass: SplitViewController.self, children: [master, detail])
let tabs = DataModel(vcClass: UITabBarController.self, mode: .reset, children: [firstTab, secondTab])
Navigator.root.window = window
Navigator.root.show(tabs)
return true
}
Show / Dismiss
Supported navigation mode: Push
, Present
, Overlay
and Popover
class DetailViewController: UIViewController {
@objc private func onTapShowViewControler() {
// Decoupling Way
let data = DataModel(vcName: "UIViewController"), mode: .push)
// Coupling Way
// If present a view contoller without passing any `UINavigationController`, it will use `Navigator.defaultNavigationControllerClass`.
let data = DataModel(vcClass: UIViewController.self, mode: .present, title: "Hello", additionalData: "You can pass any type object")
navigator?.show(data)
}
@objc private func onTapShowPopoverViewControler() {
// Show from bottom
let data = DataModel(vcClass: UIViewController.self, mode: .overlay, title: "Hello", additionalData: "You can pass any type object")
data.sourceRect = CGRect(origin: .zero, size: .init(width: 0, height: 500))
// Show in center
let data = DataModel(vcClass: UIViewController.self, mode: .popover, title: "Hello", additionalData: "You can pass any type object")
data.sourceRect = CGRect(origin: .zero, size: .init(width: 300, height: 500))
navigator?.show(data)
}
@objc private func onTapDismissViewControler() {
let data = "You can pass any type object/struct, e.g. string, tuple, dictionary and so on"
navigator?.dismiss() // 0: dimiss current view controller, 1: dismiss top two view controllers.
navigator?.dismiss(level: -1) // Dismiss to root view controller of current navigator
navigator?.dismiss(data) // Pass data to previous view controller when dismiss
}
}
DeepLink
Use Safari or other approaches to test the deep link
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// Show top view controller base on current vc stack
Navigator.current.open(url: url) { (_) -> DataModel in
// Parse the deep link url to below data model for showing
return DataModel(vcClass: TopViewController.self)
}
// Show a chain of view controllers from root vc
Navigator.root.open(url: url) { (_) -> DataModel in
// Parse the deep link url to below data models for showing
let root = DataModel(vcClass: MainViewController.self, navClass: UINavigationController.self, mode: .reset)
let middle = DataModel(vcClass: MiddleViewController.self)
let top = DataModel(vcClass: TopViewController.self)
return root --> middle --> top
}
return true
}
Transition Animation
Create custom transition class inherits the Transition
class and override below two methods. Then pass transition class with custom transition class name in data model.
class CustomTransition: Transition {
public override func animateNavigationTransition(from fromView: UIView?, to toView: UIView?) { }
public override func animatePresentingTransition(from fromView: UIView?, to toView: UIView?) { }
}
class DetailViewController: UIViewController {
@objc private func onTapShowViewControler() {
let data = DataModel(vcClass: UIViewController.self, mode: .present)
data.transitionStyle = .flipHorizontal
let data = DataModel(vcClass: UIViewController.self, mode: .present)
data.transitionName = "CustomTransition"
navigator?.show(data)
}
}
Data Receiving
class DetailViewController: UIViewController, NavigatorDataProtocol {
private var data: Any?
// Receive this callback when open by other view controller
func onDataReceiveBeforeShow(_ data: DataModel, fromViewController: UIViewController?) {
title = data.title
data = data.additionalData
}
// Receive this callback when dismiss from next view controller
func onDataReceiveAfterBack(_ data: Any?, fromViewController: UIViewController?) {
self.data = data
}
}
Latest podspec
{ "name": "SmartNavigator", "version": "1.3.2", "license": "MIT", "summary": "Generic navigation framework for view controllers", "homepage": "https://github.com/iKrisLiu/Navigator", "authors": { "Kris Liu": "[email protected]" }, "source": { "git": "https://github.com/iKrisLiu/Navigator.git", "tag": "1.3.2" }, "platforms": { "ios": "10.0" }, "swift_versions": [ "4.2", "5.0" ], "module_name": "Navigator", "source_files": "Navigator/**/*.{h,m,swift}" }
Sat, 11 May 2019 10:56:14 +0000