PageNavigator 1.1.1

PageNavigator 1.1.1

liuxc维护。



  • liuxc123

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())