Marshroute 1.0.1

Marshroute 1.0.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2023年6月
SPM支持 SPM

Tim Yusipov 维护。



  • Timur Yusipov

Marshroute

GitHub license GitHub release Swift 5.0 support cocoapods compatible

内容

概述

Marshroute 是一个库,它将鼓励你无论你更喜欢哪种架构,都将所有导航逻辑放在 Router 层。 Marshroute 有助于使你的 Router 语法简洁明了。

主要功能

  • 每个由Router驱动的转换都会转发到顶部最层的UIViewController。这意味着你可以在程序的任何位置让Marshroute显示一个视图控制器,它将简单地工作!
  • 无论你的模块是如何被展示的,你可以简单地让你的模块的Router通过调用router.dismissCurrentModule()来解散这个模块,并且它将简单地工作!你的父模块可以在未来改变展示风格(例如,以模态方式展示而不是推动),但router.dismissCurrentModule()仍然会工作!
  • 无论你的模块如何展示后续模块,你可以简单地让你的模块的Router通过调用router.focusOnCurrentModule()回到这个模块,并且它也会简单地工作!
  • Marshroute可以通过一行代码更改转换动画(更多详情请见调整转换动画
  • Marshroute支持3d触摸转换
  • Marshroute可以检测视图控制器的保留周期,并通过断言API通知你。你可以通过你的实现来覆盖默认断言:例如,将断言打印到输出或进行一些高级分析(更多详情请见插件自定义
  • Marshroute提供了一个详细的演示项目,其中描述了iPhone和iPad上的关键导航原理

详情

每个Router驱动的转换都会转发到顶部最层的UIViewController,这使得它超级容易支持DeepLink,例如从应用的任何位置展示Authorization模块。我更喜欢直接从我的根应用的Router来做这件事。

这个仓库允许你以非常干净、描述性和灵活的方式驱动你的转换。例如,以下代码似乎是从你的根应用的Router中提取的:

func showAuthorization() {
    pushViewControllerDerivedFrom { routerSeed -> UIViewController in
        let authorizationAssembly = assemblyFactory.authorizationAssembly()

        let viewController = authorizationAssembly.module(
            routerSeed: routerSeed
        )

        return viewController
    }
}

此代码将一个Authorization视图控制器推送到最顶层的UINavigationController栈中。只有当它是为Authorization模块创建一个Router时才会使用到routerSeed参数。

这里的魔法就在这一行代码中

pushViewControllerDerivedFrom { routerSeed -> UIViewController in

如果你简单地想要改变展示风格以支持模态转换,只需将其更改为

presentModalNavigationControllerWithRootViewControllerDerivedFrom { routerSeed -> UIViewController in

如果你出于某些原因不需要为你的Authorization模块一个UINavigationController,你可以通过以下方式实现

presentModalViewControllerDerivedFrom { routerSeed -> UIViewController in

再次,转换将转发到顶部,让Router保持非常简洁和直接。因此,Router只负责一件事情:选择转换的风格。

调整过渡动画

您可以通过添加动画器来自定义过渡的样式。例如

func showCategories() {
    presentModalNavigationControllerWithRootViewControllerDerivedFrom( { routerSeed -> UIViewController in
        let categoriesAssembly = assemblyFactory.categoriesAssembly()

        let viewController = categoriesAssembly.module(
            routerSeed: routerSeed
        )

        return viewController
    }, animator: RecursionAnimator())
}

这里的关键行是

}, animator: RecursionAnimator())

所以语法保持清洁,切换回原始动画样式也超级容易。

3d触摸支持

PeekAndPopUtility

想要添加花哨的窥视和弹出预览?易如反掌!只需使用PeekAndPopUtilityMarshrouteStack中,并注册您的视图控制器作为可以预览其他控制器的!

peekAndPopUtility.register(
    viewController: self,
    forPreviewingInSourceView: peekSourceView,
    onPeek: { [weak self] (previewingContext, location) in
        self?.startPeekWith(
            previewingContext: previewingContext,
            location: location
        )
    },
    onPreviewingContextChange: nil
)

peekSourceView用于在预览动画期间由UIKit捕获屏幕截图。您可以将单个视图控制器注册为在多个源视图中预览(例如:在表格视图中和在导航栏中)。

onPeek闭包将在peekSourceView中发生强触控手势时被调用。在您的startPeekWith(previewingContext:location:)方法中,您应该执行以下操作:

  1. 找到用户与之交互的视图(交互视图)。您应该在previewingContext.sourceView的坐标系中使用指定的location

  2. 调整previewingContextsourceRect。您应该将那个交互视图的帧转换到previewingContext.sourceView的坐标系。UIKit使用sourceRect在用户按下时保持其视觉效果,同时在周围内容上应用模糊。

  3. 调用过渡,这在用户简单地点击同一location时通常发生。例如,如果用户按下一个UIControl,您可以调用sendActions(for: .touchUpInside)来调用该UIControl的动作处理程序。

假设上述提到的行为处理器最终导致某些路由器调用pushViewControllerDerivedFrom(_:)来推入一个新的视图控制器。在这种情况下,实际上不会发生推送。取而代之的是,Marshroute将冻结转换并预览目标视图控制器。只有当用户提交预览(即退出预览)时,转换才会最终执行。

上述描述的行为仅在活动peek请求期间发生(当UIViewControllerPreviewingDelegate请求预览视图控制器时)。在所有其他情况下,pushViewControllerDerivedFrom(_:)将立即推入,如预期的那样。

重要提示:如果您在onPeek闭包中没有调用任何转换,或者调用异步转换,则不会发生预览。这种行为是由于UIKit Api的限制:UIViewControllerPreviewingDelegate需要同步返回预览视图控制器。

您还可以使用onPreviewingContextChange闭包来设置您的手势识别器失败关系。

预览和移除状态观察

您可以使用来自MarshrouteStackPeekAndPopStateObservable来观察任何视图控制器的peekpop状态变化。这可能对分析目的有用。

peekAndPopStateObservable.addObserver(
    disposable: self,
    onPeekAndPopStateChange: { viewController, peekAndPopState in
        debugPrint("viewController: \(viewController) changed `peek and pop` state: \(peekAndPopState)")
    }
)

您还可以使用PeekAndPopStateViewControllerObservable来观察您特定的视图控制器的peekpop状态变化。这可能有助于在peekpopped模式下调整视图控制器的外观。

peekAndPopStateViewControllerObservable.addObserver(
    disposableViewController: self,
    onPeekAndPopStateChange: { [weak self] peekAndPopState in
        switch peekAndPopState {
        case .inPeek:
            self?.onPeek?()
        case .popped:
            self?.onPop?()
        case .interrupted:
            break
        }
    }
)

在这里,在onPeekonPop闭包中,您的Presenter可以强制视图根据其UI进行更新。

view?.onPeek = { [weak self] in
    self?.view?.setSimilarSearchResultsHidden(true)
}

view?.onPop = { [weak self] in
    self?.view?.setSimilarSearchResultsHidden(false)
}

演示

查看演示项目。这个演示是用Swift编写的,使用VIPER架构,显示了Router现在具备的所有功能。

在模拟器上运行此演示,并检查模拟内存警告或设备震动时会发生什么。您将看到由根模块的Router(即UITabBarControllerRouter)驱动的几种类型的转换。

此演示项目针对iPhoneiPad,并为每个受支持的设备 intentions 创建独特的Router实现,从而强调了将导航逻辑从View层移动到Router层的价值。

当您轻触一个蓝色计时器图块时,您将为此图块所属的模块安排一个反向转换。为了看到这种效果,您应该在导航堆栈中进行多次转换。

从0.4.0版本开始,演示项目更新为显示PeekAndPopUtility的实际操作:您可以通过按下任何表格视图单元格或导航栏按钮来预览底层转换。您还可以了解如何使用PeekAndPopStateViewControllerObservable来调整AdvertisementViewControllerpeekpopped模式下的外观:在peek模式下,您将只看到一个全屏的彩色图像图案,而在popped模式下,您还将看到一个类似的广告部分。

要求

  • iOS 9.0+
  • Xcode 14.0+

注意:peek和pop仅支持iOS 9.0+

安装

Cocoapods

要使用CocoaPods安装Marshroute,请在您的Podfile中添加以下行

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!

pod 'Marshroute'

然后运行pod install命令。有关CocoaPods安装和使用详情,请访问其官方网站

Carthage

要使用Carthage安装Marshroute,请将以下行添加到您的Cartfile

github "avito-tech/Marshroute" ~> 1.0.0

然后运行 carthage update --platform iOS 命令。有关 Carthage 的安装和使用详情,请访问 其仓库网站

自定义

您可以使用 MarshroutePrintPluginMarshrouteAssertionPlugin 提供自定义打印和断言实现。这就像这样

MarshroutePrintManager.setUpPrintPlugin(YourPrintPlugin())
MarshrouteAssertionManager.setUpAssertionPlugin(YourAssertionPlugin())

许可证

MIT

Objective-c 支持

该框架是用纯 Swift 编写的,使用了其最新的功能,因此如果您想在您的 Objective-c 应用中使用 Marshroute,您将不得不用 Swift 编写您的 Router

有用链接

您可以观看 此视频 了解形成 Marshroute 基础的原因和想法(俄语)。

您还可以阅读 这篇指南,了解如何在您的应用中实现 DeepLink 支持时使用 Marshroute

作者

Timur Yusipov ([email protected], [email protected], https://twitter.com/Fizmatchel, https://stackoverflow.com/users/2982854/tim).