此仓库包含一个库,该库实现了 Coordinator 模式。Coordinator 模式是一种在 iOS 应用程序开发中用于管理应用程序导航流程的设计模式。该库提供了一组可用于实现 Coordinator 流程的功能。此库不使用任何 UIKit 组件。
要在您的 iOS 项目中使用 SUICoordinator 库,您需要将库文件添加到您的项目中。以下是基本步骤:
首先,让我们定义路径和视图。
import SwiftUI
import SUICoordinator
enum HomeRoute: RouteType {
case push(viewModel: PushViewModel)
case sheet(viewModel: SheetViewModel)
case fullscreen(viewModel: FullscreenViewModel)
case detents(viewModel: DetentsViewModel)
case actionListView(viewModel: ActionListViewModel)
var presentationStyle: TransitionPresentationStyle {
switch self {
case .push:
return .push
case .sheet:
return .sheet
case .fullscreen:
return .fullScreenCover
case .detents:
return .detents([.medium])
case .actionListView:
return .push
}
}
@ViewBuilder
var view: Body {
switch self {
case .push(let viewModel):
PushView(viewModel: viewModel)
case .sheet(let viewModel):
SheetView(viewModel: viewModel)
case .fullscreen(let viewModel):
FullscreenView(viewModel: viewModel)
case .detents(let viewModel):
DetentsView(viewModel: viewModel)
case .actionListView(let viewModel):
NavigationActionListView(viewModel: viewModel)
}
}
}
其次,让我们创建第一个 Coordinator。 所有 Coordinator 都应该实现 start()
函数,然后启动流程(强制性)。 最后,添加额外的流程。
import SUICoordinator
class HomeCoordinator: Coordinator<HomeRoute> {
override func start(animated: Bool = true) async {
let viewModel = ActionListViewModel(coordinator: self)
await startFlow(route: .actionListView(viewModel: viewModel), animated: animated)
}
func navigateToPushView() async {
let viewModel = PushViewModel(coordinator: self)
await router.navigate(to: .push(viewModel: viewModel))
}
func presentSheet() async {
let viewModel = SheetViewModel(coordinator: self)
await router.navigate(to: .sheet(viewModel: viewModel))
}
func presentFullscreen() async {
let viewModel = FullscreenViewModel(coordinator: self)
await router.navigate(to: .fullscreen(viewModel: viewModel))
}
func presentDetents() async {
let viewModel = DetentsViewModel(coordinator: self)
await router.navigate(to: .detents(viewModel: viewModel))
}
func presentTabbarCoordinator() async {
let coordinator = CustomTabbarCoordinator()
await navigate(to: coordinator, presentationStyle: .sheet)
}
func close() async {
await router.close()
}
func finsh() async {
await finishFlow(animated: true)
}
}
然后,让我们创建一个 View 及其 ViewModel。
import Foundation
class ActionListViewModel: ObservableObject {
let coordinator: HomeCoordinator
init(coordinator: HomeCoordinator) {
self.coordinator = coordinator
}
@MainActor func navigateToFirstView() async {
await coordinator.navigateToPushView()
}
@MainActor func presentSheet() async {
await coordinator.presentSheet()
}
@MainActor func presentFullscreen() async {
await coordinator.presentFullscreen()
}
@MainActor func presentDetents() async {
await coordinator.presentDetents()
}
@MainActor func presentTabbarCoordinator() async {
await coordinator.presentTabbarCoordinator()
}
@MainActor func finish() async {
await coordinator.finish()
}
}
import SwiftUI
struct NavigationActionListView: View {
typealias ViewModel = ActionListViewModel
@StateObject var viewModel: ViewModel
var body: some View {
List {
Button("Push NavigationView") {
Task { await viewModel.navigateToPushView() }
}
Button("Presents SheetView") {
Task { await viewModel.presentSheet() }
}
Button("Presents FullscreenView") {
Task { await viewModel.presentFullscreen() }
}
Button("Presents DetentsView") {
Task { await viewModel.presentDetents() }
}
Button("Presents Tabbar Coordinator") {
Task { await viewModel.presentTabbarCoordinator() }
}
}
.navigationTitle("Navigation Action List")
}
}
import SwiftUI
import SUICoordinator
class AppDelegate: NSObject, UIApplicationDelegate {
var mainCoodinator: HomeCoordinator?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
) -> Bool {
mainCoodinator = HomeCoordinator()
// Simulate the receipt of a notification or external trigger to present some coordinator
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
Task { [weak self] in
// Create and present the CustomTabbarCoordinator in a sheet presentation style
let coordinator = CustomTabbarCoordinator()
try? await coordinator.forcePresentation(
presentationStyle: .sheet,
mainCoordinator: self
)
}
}
return true
}
}
import SwiftUI
@main
struct SUICoordinatorDemoApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
appDelegate.mainCoodinator?.getView()
}
}
}
为了更好地理解,我建议您查看位于 Example 文件夹中的示例项目。
以下是您可以执行的最重要的特性和操作:
要在 SUICoordinator
中创建任何路由,您需要将您的对象扩展到 RouteType
协议; 此外,如果需要,您可以添加自定义函数。 正如您所看到的,在我们的示例中,我们使用自定义类型 (enums
) 来实现它。
最后但并非最不重要的一点是,您还可以使用 DefaultRoute
创建自定义路由,如 TabBarFlowCoordinator
示例中所示
Router 负责管理导航堆栈并协调不同视图之间的转换。 它从视图中抽象出导航细节,使它们能够专注于其特定功能,例如:
名称 | 参数 | 描述 |
---|---|---|
navigate(_) |
|
是一个异步函数,允许您在 Route 中定义的视图之间导航。 presentation 的类型包括 Push、Sheet、Fullscreen 和 Detents |
present(_) |
|
是一个异步函数,呈现一个视图,例如 Sheet、Fullscreen 或 Detents |
pop(_) |
|
是一个异步函数,从导航堆栈中弹出顶部视图并更新显示。 |
popToRoot(_) |
|
是一个异步函数,弹出堆栈上的所有视图,除了根视图并更新显示。 |
dismiss(_) |
|
是一个异步函数,关闭视图以模态方式呈现的视图。 |
popToView(_) |
|
是一个异步函数,弹出视图,直到指定的视图位于导航堆栈的顶部。 示例:router.popToView(MyView.self) |
close(_) |
|
是一个异步函数,关闭或弹出在 Coordinator 中呈现的最后一个视图。 |
作为视图的单独实体,将导航逻辑与呈现逻辑分离。 这种关注点分离使视图能够专注于其特定功能,而 Navigation Coordinator 负责应用程序的整体导航流程。 一些特性是:
名称 | 参数 | 描述 |
---|---|---|
router |
Route 类型的变量,允许执行 router 操作。 | |
startFlow(_) |
|
是一个异步函数,清除导航堆栈并运行导航流程。 |
finishFlow(_) |
|
是一个异步函数,弹出堆栈上的所有视图,包括根视图,关闭所有模态视图,并从 coordinator 堆栈中删除当前的 coordinator。 |
forcePresentation(_) |
|
是一个异步函数,将当前 coordinator 放在 coordinator 堆栈的顶部,使其成为活动和可见的 coordinator。 此功能对于从推送通知、通知中心、非典型流程等启动导航流程非常有用。 |
navigate(_) |
|
是一个异步函数,允许您在 Coordinator 之间导航。 它调用 start() 函数。 |
finishFlow(_) |
|
是一个异步函数,弹出堆栈上的所有视图,包括根视图,关闭所有模态视图,并从 coordinator 堆栈中删除当前的 coordinator。 |
它的工作方式与 Coordinator 相同,但具有以下附加功能:
名称 | 参数 | 描述 |
---|---|---|
currentPage |
Page 类型的变量,允许设置和获取所选的标签 |
|
getCoordinatorSelected() |
|
返回与所选标签关联的选定的 coordinator |
setPages(_) |
|
是一个异步函数,更新页面集。 |
getCoordinator(_) |
|
返回给定位置的 coordinator 作为参数 |
setBadge |
|
允许设置标签的徽章的变量 |
customView |
|
是一个接收视图作为参数的闭包,用于创建自定义标签栏 |
SPM
打开 Xcode 和你的项目,点击 File / Swift Packages / Add package dependency...。 在文本框 "Enter package repository URL" 中,写入 https://github.com/felilo/SUICoordinator 并按两次 Next
欢迎对 SUICoordinator 库做出贡献! 要做出贡献,只需 fork 此存储库并在新分支中进行更改。 当您的更改准备好后,提交拉取请求到此存储库以供审核。