LightRoute
描述
LightRoute 是在纯 Swift 上实现的 VIPER 模块之间的简单过渡。我们可以通过与几行代码之间的转变很容易地在模块之间进行转换。
安装
CocoaPods
添加到 podfile 中
pod "LightRoute"
Carthage
Carthage 是一个去中心化的依赖管理器,它会构建依赖关系并为您提供二进制框架。
您可以使用以下命令通过 Homebrew 安装 Carthage:
$ brew update
$ brew install carthage
要使用 Carthage 将 LightRoute 集成到您的 Xcode 项目中,请在您的 Cartfile
中指定它。
github "SpectralDragon/LightRoute" ~> 2.1
运行 carthage update
来构建框架,并将构建的 LightRoute.framework
拖入您的 Xcode 项目中。
Swift Package Manager
一旦您设置了Swift包,将 LightRoute 添加为依赖关系就像将它添加到您的 Package.swift
中的 dependencies 值一样简单。
Swift 3
dependencies: [
.Package(url: "https://github.com/SpectralDragon/LightRoute.git", majorVersion: 2)
]
Swift 4
dependencies: [
.package(url: "https://github.com/SpectralDragon/LightRoute.git", from: "2.1")
]
示例
- 新示例项目: iOS 示例
- 旧示例项目: Viper-LightRoute-Swinject
关于 LightRoute
LightRoute 可以与 Segue
、UINavigationController
和默认的视图控制器显示方式协同工作。
对于所有过渡,返回一个管理当前过渡的 TransitionNode
实例。您可以随意更改过渡流程。
如何使用
例如,我们将过渡到两个 VIPER 模块之间
import LightRoute
// MARK: - The module initiating the transition.
protocol FirstViperRouterInput: class {
func openModule(userIdentifier: String)
}
final class FirstViperRouter: FirstViperRouterInput {
// This property contain protocol protected view controller for transition.
weak var transitionHandler: TransitionHandler!
// View controller identifier for current storyboard.
let viewControllerIdentifier = "SecondViperViewController"
func openModule(userIdentifier: String) {
try? transitionHandler
// Initiates the opening of a new view controller.
.forCurrentStoryboard(resterationId: viewControllerIdentifier, to: SecondViperViewControllerModuleInput.self)
// Set animate for transition.
.transition(animate: false)
// Set transition case.
.to(preffered: TransitionStyle.navigation(style: .push))
// View controller init block.
.then { moduleInput in
moduleInput.configure(with: userIdentifier)
}
}
}
// MARK: - The module at which the jump occurs.
// Module input protocol for initialize
protocol SecondViperViewControllerModuleInput: class {
func configure(with userIdentifier: String)
}
final class SecondViperPresenter: SecondViperViewControllerModuleInput, ... {
// Implementation protocol
func configure(with userIdentifier: String) {
print("User identifier", userIdentifier) // Print it!
// Initialize code..
}
}
在这种情况下,您会创建默认的视图控制器之间的过渡,并按您的要求配置模块输入。但您也可以仅使用视图控制器,例如
.forCurrentStoryboard(resterationId: viewControllerIdentifier, to: SecondViperPresenter.self)
/// and etc..
注意❗️ moduleInput
- 默认情况下,该属性包含目标视图控制器中的 output
属性。您可以使用 selector:
方法来更改它。您可以使用以下方法获取自定义的 moduleInput。
- 通过字符串:
selector(_ selector: String)
- 通过选择器:
selector(_ selector: Selector)
- 通过键路径:
selector(_ selector: KeyPath)
过渡情况
例如,我们分析这段代码,包含两种处理过渡的情况。
第一种情况
这是默认情况,使用默认的 LightRoute 实现。如果您只想显示新的模块,则可以使用该方法
try? transitionHandler
// Initiates the opening of a new view controller.
.forCurrentStoryboard(resterationId: viewControllerIdentifier, to: SecondViperViewControllerModuleInput.self)
// Setup module input.
.then { moduleInput in
moduleInput.configure(with: "Hello!")
}
第二种情况
但第一种方法不足以灵活,因此有 customTransition()
方法。该方法返回 CustomTransitionNode
。此节点不支持默认的 TransitionNode
方法。 CustomTransitionNode
是一个类,用于灵活配置您的过渡,但针对此过渡流程,您应该实现自己的过渡逻辑,并调用 set(_ didPerformCustomTransition:)
或 perform()
方法来激活过渡。
示例
try? transitionHandler
// Initiates the opening of a new view controller.
.forCurrentStoryboard(resterationId: viewControllerIdentifier, to: SecondViperViewControllerModuleInput.self)
// Activate custom transition.
.customTransition()
// Custom transition case.
.transition { source, destination in
// Implement here your transition logic, like that:
// source.present(destination, animated: true, completion: nil)
}
// Setup module input.
.then { moduleInput in
moduleInput.configure(with: "Hello custom transition!")
}
自定义过渡
要自定义您的过渡,您可以更改过渡的展示方式并设置动画。
动画过渡
此方法可以为您当前的过渡动画。
.transition(animate: false)
更改展示方式
方法 to(preffered:)
负责更改展示风格。它与 UINavigationController、UISplitViewController、ModalPresentation 和默认展示方式一起工作。
.to(preferred: TransitionStyle)
- 导航风格(
push
、pop
、present
).to(preferred: .navigation(style: NavigationStyle))
- 分割风格(
detail
、default
).to(preferred: .split(style: SplitStyle))
- 模态风格(
UIModalTransitionStyle
、UIModalPresentationStyle
- 标准 UIKit 展示风格。).to(preferred: .modal(style: style: (transition: UIModalTransitionStyle, presentation: UIModalPresentationStyle)))
配置目标控制器
有时您需要在控制器中添加额外的依赖项。为此,我们将添加 apply(to:)
方法。该方法返回目标控制器,您可以对其进行配置。
try? transitionHandler
.forSegue(identifier: "LightRouteSegue", to: SecondViperViewControllerModuleInput.self)
.apply(to: { controller in
// configure your controller.
})
.then { moduleInput in
// configure your module
}
在新的故事板中进行过渡
同样,LightRoute 可以像这样在新的故事板实例上进行过渡。
// We remeber this class :)
func openModule(userIdentifier: String) {
let storyboard = UIStoryboard(name: "NewStoryboard", bundle: Bundle.main)
let factory = StoryboardFactory(storyboard: storyboard)
try? transitionHandler
// Initiates the opening of a new view controller from custom `UIStoryboard`.
.forStoryboard(factory: factory, to: SecondViperViewControllerModuleInput.self)
// Set animate for transition.
.transition(animate: false)
// View controller init block.
.then { moduleInput in
moduleInput.configure(with: userIdentifier)
} // If you don't want initialize view controller, we should be use `.perform()`
}
Segue 过渡
您可以通过以下方式从 UIStoryboardSegue
触发过渡
func openModule(userIdentifier: String) {
try? transitionHandler
// Performs transition from segue and cast to need type
.forSegue(identifier: "LightRouteSegue", to: SecondViperViewControllerModuleInput.self)
.then { moduleInput in
moduleInput.setup(text: "Segue transition!")
}
}
如果您想使用 EmbedSegue
,需要在故事板中添加 segue,设置类为 EmbedSegue
,并且源视图控制器必须符合协议 ViewContainerForEmbedSegue
,如下所示
extension SourceViewController: ViewContainerForEmbedSegue {
func containerViewForSegue(_ identifier: String) -> UIView {
return embedView
}
}
然后您可以按如下方式触发 EmbedSegue
过渡
func addEmbedModule() {
try? transitionHandler
.forSegue(identifier: "LightRouteEmbedSegue", to: EmbedModuleInput.self)
.perform()
}
关闭当前模块
如果您想关闭当前模块,应使用以下方法
.closeCurrentModule()
之后,您可以使用 perform()
方法来触发关闭方法。
动画关闭过渡
此方法可以为您当前的过渡动画。
.transition(animate: false)
注意:默认值为 true
自定义关闭样式
如果您想关闭弹出控制器或使用 popToRoot 控制器,必须执行方法 preferred(style:)
。此方法为您的关闭过渡提供不同的样式。
如果您需要为自定义控制器调用 popToViewController(:animated)
,必须执行方法 find(pop:)
。
try? transitionHandler
.closeCurrentModule()
.find(pop: { controller -> Bool
return controller is MyCustomController
})
.preferred(style: .navigation(style: .findedPop))
.perform()
支持 UIViewControllerTransitioningDelegate
LightRoute 2.0 开始支持 UIViewControllerTransitioningDelegate 进行过渡。我们可以使用以下方法进行操作
.add(transitioningDelegate: UIViewControllerTransitioningDelegate)
注意
- 设计者: ViperMcFlurry
- 许可证:
MIT
- 作者: Vladislav Prusakov / [email protected]
感谢观看。