AppRouter 5.1.0

AppRouter 5.1.0

测试已测试
编程语言语言 SwiftSwift
许可证 MIT
发布时间最后发布2018年10月
SPM支持 SPM

Artem Antihevich 维护。



AppRouter 5.1.0

AppRouter Logo

构建状态   codecov.io CocoaPod 平台   CocoaPod 版本   Carthage 兼容 Packagist

非常简单的方式来处理控制器的创建/展示/导航以及降低项目的总体耦合度。

要求

  • iOS 8.0+
  • macOS 10.10+ (仅限 RxSwift 子规格)
  • Xcode 9+
  • Swift 4

示例

1. 在应用程序启动时,您可能需要设置主控制器,只需

try? MainTabBarController.presenter().setAsRoot()

2. 然后在某个时候——显示搜索控制器

try? SearchController.presenter().embedInNavigation().present()

3. 然后您想推送用户选择的产品控制器

try? ProductDetailsController.presenter().configure{
  $0.product = userSelectedProduct
}.push()

以下示例假设您为每个控制器类型使用单独的故事板。

注意:建议为每个控制器单独创建故事板,这样对于每种控制器类型,您将拥有一个类似下面的单独文件夹

UIViewControllerType.storyboard
UIViewControllerType.swift
UIViewControllerTypeViewModel.swift
UIViewControllerTypeViewModelTests.swift

别忘了在故事板中将您的控制器标记为初始,这将允许您使用 Presenter 的默认配置。

安装

CocoaPods

pod 'AppRouter'
pod 'AppRouter/Route'

RxSwift 用于 AppRouter 的生命周期可观察扩展:警告: RxSwift subspec 已不再包含 Core

pod 'AppRouter'
pod 'AppRouter/RxSwift'

Carthage

github "MLSDev/AppRouter"

内容

易于访问的应用程序

// provides access to keyWindow (also creates one if current is nil)
AppRouter.window

// root controller in current window stack
AppRouter.rootViewController

// topmost controller
AppRouter.topViewController

// returns instance of passed type if its present in tabBar (even if it's embedded in navigationController)
tabBarController.getControllerInstance<T: UIViewController>(_:) -> T?

// returns instance of passed type if its present in navigationController
navigationController.getControllerInstance<T: UIViewController>(_:) -> T?

// returns true if current controller modally presented
viewController.isModal

简单搭建、配置、展示

当然,最好是将控制器创建、配置和展示逻辑从其他控制器和视图中提取出来,放入FlowControllers或者简单的扩展方法(如果您希望这个新控制器工作有效 - 给它们完成块或尝试使用响应式方法)。这将显著减少一致性,并允许您在整个应用程序中只修改一个地方来更改功能背后的逻辑。

extension AppRouter {
  static func openGridPictureGalleryControllerWith(pictures: PicturesRepresentation) {
    try? GridPictureGalleryController.presenter().fromStoryboard("GridPictureGallery").embedInNavigation().configure{
      $0.picturesRepresentation = pictures
    }.present()
  }
  static func openChangePasswordController() {
    try? ChangePasswordViewController.presenter().push()
  }
}

注意:框架默认使用您的UIViewController子类的名称(String(describing: controllerType))作为Storyboard标识符以及初始控制器(或根ViewController在初始 UINavigationController)

一般来说 - presenter()返回从其调用的ViewController类相关的配置。这种配置允许您指定如何创建控制器,展示前需要做什么,结果控制器应该在何处展示或推送等。

所有配置方法是文档化的,所以请在使用前阅读。一些可用的方法

指定view controller的来源

func fromStoryboard(_ name: String?, initial : Bool) - 将尝试从指定的Storyboard创建控制器。

func fromXib(_ name: String?) - 将尝试从Xib创建。

func from(provider: @escaping () throws -> T) - 将使用提供的工厂方法创建。

指定目标

func onTop() - 将使用AppRouter.topViewController作为目标。

func onRoot() - 将使用AppRouter.rootViewController。

func on(_ provider: @escaping () throws -> UIViewController) - 将使用提供的控制器。

注意控制器创建、目标解析以及所有其他配置步骤仅在实际调用展示方法(pushpresentsetAsRootshow)时执行

是否应该将控制器嵌入到某个对象中?

func embedInNavigation(_ navigationController: @autoclosure @escaping () -> UINavigationController - 如果需要从导航控制器中获取控制器。《code>func embedIn(_ embederBlock: @escaping (T) throws -> UIViewController) - 如果需要一些自定义嵌入规则。

在执行显示动作之前进行额外的配置

func configure(_ label: CustomStringConvertible, _ configuration: @escaping (T) throws -> ()) - 可以用来额外配置控制器。

显示控制器

func present() - 此动作将从您指定的源构建控制器,如果需要,将其嵌入,使用您的额外配置进行配置,解析要显示的目标,然后...显示。

func push() - 与之前相同,但需要目标控制器本身或在其中(使用ontoViewController.property动来使用)。将推送而不是显示。

func show() - 全部由您处理(您可以通过handleShow方法来设置它)。

完成处理程序

除了UIKit提供的显示/消失完成块外,AppRouter还提供了您用于在导航堆栈中推送/弹出控制器的完成块。

pushViewController(_, animated:, completion:)
popViewController(animated animated:, completion:)
popToViewController(_:, animated:, completion:)
popToRootViewController(animated animated:, completion:)
popToViewController<T: UIViewController>(_:, animated:, completion:)

如何关闭控制器?

另一个可能的场景:功能控制器可以被推送到应用程序的不同部分。使此类控制器消失(通过关闭按钮等)的简单方法是用关闭方法。只需

@IBAction func closeTapped(sender: UIButton!) {
  self.close()
}

就是这样。该方法将尝试检测正确的控制器消失方式。

RxSwift 扩展

如果您想找到一种简单的方式来处理控制器生命周期之外的内容,请尝试使用 AppRouter/RxSwift 子规范。它提供了一组关于生命周期方法的类型和实例可观察对象(它从您订阅的那一刻起使用混入)。

instance.rx.onViewDidLoad() -> Signal<Void>
instance.rx.onViewWillAppear() -> Signal<Bool>
instance.rx.onViewDidAppear() -> Signal<Bool>
instance.rx.onViewWillDisappear() -> Signal<Bool>
instance.rx.onViewDidDisappear() -> Signal<Bool>

Type.rx.onViewDidLoad() -> Signal<Type>
Type.rx.onViewWillAppear() -> Signal<(controller: Type, animated: Bool)>
Type.rx.onViewDidAppear() -> Signal<(controller: Type, animated: Bool)>
Type.rx.onViewWillDisappear() -> Signal<(controller: Type, animated: Bool)>
Type.rx.onViewDidDisappear() -> Signal<(controller: Type, animated: Bool)>

Route 子规范

在 MVVM 世界中使用 Dip、ReusableView 的高级 Presenter.Configuration 被称为 'Route'。它提供了解决 ViewController/ViewModel 的能力,使用 viewModelFactory/viewFactory。

作者

Artem Antihevich,[email protected]

许可证

ReusableView 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。