PageNavigator
一个简单的应用程序内导航框架,用于替换繁琐的导航逻辑。
要求
- iOS 8.0及以后
- Swift 5.0
安装
pod 'PageNavigator'
如何工作
创建一个导航器
/// NavigationController container based navigator
let navigator = NavNavigator(window: UIWindow())
/// TabBarController container based navigator
let navigator = TabNavigator(window: UIWindow())
/// Custom container based navigator
let navigator = ContainerNavigator(window: UIWindow())
导航器是主要的入口点。
创建场景并进行注册
extension SceneName {
static let login: SceneName = "Login"
}
class LoginScene: SceneHandler {
var name: SceneName {
return .login
}
func view(with parameters: Parameters) -> UIViewController {
let vc = UIViewController()
vc.view.backgroundColor = .red
return vc
}
/// Optional
func reload(_ viewController: UIViewController, parameters: Parameters) {
// Do nothing by default
}
/// Optional
var isReloadable: Bool {
return true
}
}
navigator.register(LoginScene())
设置根场景并进行导航!
navigator.root(.login)
navigator.push(.someScene)
根场景是将要设置为其 UIWindow 的 rootViewController 的场景。
支持URL
注册URL
- 为场景注册URL
navigator.register("navigator://collection") { (url, values, context) -> SceneContext? in
return SceneContext(sceneName: .collection, parameters: url.queryParameters, type: .push, isAnimated: true)
}
- 为句柄注册URL
navigator.handle("navigator://toast") { (url, values, context) -> Bool in
print("handle: \(url.queryParameters["text"] ?? "")")
return true
}
打开URL
navigator.url("navigator://toast")
// or
navigator.push(for: "navigator://toast")
navigator.present(for: "navigator://toast")
功能
-
展示
navigator.present(.login)
-
在导航控制器内展示
navigator.presentNavigation(.someScene)
-
关闭所有视图
navigator.dismiss()
-
关闭第一个视图
navigator.dismiss()
-
按场景关闭
navigator.dismiss(.someScene)
-
推入
navigator.push(.someScene)
-
回退到根视图
navigator.popToRoot()
-
重新加载
navigator.reload(.someScene)
调用场景处理程序的 reload 方法。
-
触控预览
navigator.preview(.someScene, from: someViewController, at: someSourceView)
-
弹出菜单展示
navigator.popover(.someScene, from: somView)
-
过渡动画
navigator.transition(to: .someScene, with: someInteractiveTransition)
-
视图创建
let loginView = navigator.view(for: .login)
-
遍历(获取当前堆栈层次;场景名称和展示类型)
navigator.traverse { state in if state.names.contains(.collection) { // Do something } }
-
使用构建器进行相对堆栈导航
navigator.build { builder in builder.modal(.contact) builder.modalNavigation(.detail) // Modal presentation with a navigation controller. builder.push(.avatar) }
如果你使用相对导航,你可以在当前层次结构之上添加新场景。
-
使用构建器进行绝对堆栈导航(如果可能的话,当前堆栈将被回收和重新加载)
navigator.build { builder in builder.root(name: .home) builder.modalNavigation(.login) }
如果您使用绝对导航,将重新从根建立层次结构。如果当前层次结构与目标层次结构匹配,则视图控制器将被回收和重新加载。
使用绝对导航来显示任何当前状态的特定层次结构。
-
基于操作的导航
对于更复杂的导航,您可以通过创建和串联操作来执行并行执行。这可以通过创建一个新的SceneOperation并扩展Navigator协议来轻松实现。
class SomeOperation { fileprivate var scenes: [Scene] fileprivate let renderer: SceneRenderer init(scenes: [Scene], renderer: SceneRenderer) { self.scenes = scenes self.renderer = renderer } } extension SomeOperation: SceneOperation { func execute(with completion: CompletionBlock?) { let dismissAllOperation = renderer.dismissAll(animated: true) let addScenes = renderer.add(scenes: scenes) let reloadLast = renderer.reload(scene: scenes.last!) let complexOperation = dismissAllOperation .then(addScenes) .then(reloadLast) .execute(with: completion) } }
-
拦截器
通过实现SceneOperationInterceptor协议,您可以拦截由导航器执行的所有操作。此协议允许您在某些情况下改变导航器的行为。
例如,在呈现某些编辑联系视图之前,显示联系权限提醒。
class ContactsPermissionsInterceptor: SceneOperationInterceptor { func operation(with operation: SceneOperation, context: SceneOperationContext) -> SceneOperation? { return ShowContactPermissionsIfNeededSceneOperation().then(operation) } func shouldIntercept(operation: SceneOperation, context: SceneOperationContext) -> Bool { return context.targetState.names.contains(.editContact) } }
如果您想停止操作的执行,必须在operation(with:context:)上返回nil。
要开始拦截,需要注册拦截器。
navigator.register(ContactsPermissionsInterceptor())