NavigationRouter

SwiftUI NavigationStack 的替代方案。NavigationRouter 在利用 NavigationStack 提升性能的同时,还能更好地控制导航。它还提供了简便的编程式导航方法。NavigationRouter 是类型安全的,并且避免使用 AnyView 以尽可能提高性能。

安装

Swift Package Manager

Swift Package Manager 是一种用于自动化 Swift 代码分发的工具,并且集成到 Swift 编译器中。

要将 SwiftUI-Navigation-Router 添加到你的项目中,请执行以下操作。

快速入门指南

添加 Navigation Router

NavigationRouter 是一个视图,用于替代 NavigationStack。它模拟了 NavigationStack 的所有功能,并在许多方面增加了灵活性。为了使用它,我们首先需要导入 NavigationRouter 模块。

import SwiftUI
import NavigationRouter

然后,你可以替换当前的 NavigationStack,或者(如果在新项目中)将 NavigationRouter 放在你的根视图中。 像这样

struct RootView: View {
    var body: some View {
        NavigationRouter {
            HomeView()
        }
    }
}

添加可导航的视图

为了导航到不同的视图,NavigationRouter 需要知道哪些视图是可导航的。你可以使用 routerDestinations ViewModifier 轻松地做到这一点。 你可以将它们全部添加到你的根视图中,或者沿路线指定它们。 这是前者的演示。

struct RootView: View {
    var body: some View {
        NavigationRouter {
            HomeView()
                .routerDestinations(ViewTwo.self, ViewThree.self)
                .routerDestinations(ViewFour.self)
        }
    }
}

向前导航 / 推送视图

添加了 NavigationRouter 并添加了你的 Navigable Views 之后。 你可以开始导航了。 向前导航 / 推送视图非常简单! 你可以使用 PushView,或者使用 @NavRouter 属性包装器访问 Router,然后调用 push 函数。

使用 PushView

使用 PushView 是向前导航的最简单方法。 在你需要导航的任何文件中,导入 NavigationRouter,然后就像使用 NavigationLink 一样简单。 可以使用 String 或自定义标签 View 创建 PushView

注意:PushView 的功能类似于 NavigationLinkButton 注意:PushViewNavigationLink 的替代品,在 NavigationRouter 中使用 NavigationLink 会导致断言失败

struct ViewOne: View {
    var body: some View {
        VStack {
            // Using a Text for its View.
            PushView("Navigate to View Two", destination: ViewTwo())
            
            // Or
            
            // Using a Custom Label for its View.
            PushView(ViewTwo()) {
                // Custom Label View.
                Image("MyNavigationImage")
            }
        }
    }
}

使用编程式向前导航

使用 Navigation Router 进行编程式导航几乎与使用 PushView 一样简单。 我们只需要一个额外的步骤。 我们需要手动访问我们的 Router。 我们可以使用 @NavRouter 属性包装器来实现。

struct ViewOne: View {
    
    // You can name this variable whatever, router is what we will use for these examples.
    @NavRouter var router
    
    var body: some View {
        // View Body...
    }
}

现在我们可以访问我们的 Router,我们可以用它来导航。 要推送一个视图,就像调用 push 函数一样简单。 通常你可能会在 ButtononTapGesture 中执行此操作; 但是,你可以在需要它的任何地方调用它,这就是使用编程式导航的魅力所在。

var body: some View {
    Button("Navigate To View Two") {
        router.push(ViewTwo())
    }
}

使用编程式导航时,我们可以使用 push 函数的附加参数。 此参数是一个 [String : Any] 字典。 这使你可以将一些附加信息绑定到你的 View 以用于特定目的。

router.push(ViewTwo(), with: ["name" : "View Two", "totalViews" : 6])

向后导航 / 弹出视图

SwiftUI 的 NavigationStack 提供了非常有限的向后导航。 你可以返回一次、返回一定的次数或返回到根目录。 但是导航并不总是那么简单。 通常你可能不知道你需要返回多少次,或者你想返回到特定的视图,或者可能为用户提供一种查看他们可以返回的所有不同位置的方法。 这就是 SwiftUI-Navigation-Router 的用武之地。 Router 提供了许多向后导航的方法,无论是编程式的还是使用 PopView

默认情况下,SwiftUI 的 NavigationStack 中未包含的向后导航方式示例包括

可以使用 PopView 或编程式地使用 Router 完成上述所有操作,包括 SwiftUI 的 NavigationStack 中已经包含的内容。

使用 PopView

使用 PopView 是向后导航的最简单方法。 在你需要从其向后导航的任何文件中,导入 NavigationRouter,然后就像使用 NavigationLink 一样简单。 可以使用 String 或自定义标签 View 创建 PopView

注意:PopView 的功能类似于 NavigationLinkButton

struct ViewTwo: View {
    var body: some View {
        VStack {
            // Using a Text for its View.
            PopView("Go Back One View")
            
            // Or
            
            // Using a Custom Label for its View.
            PopView {
                // Custom Label View.
                Image("BackOneViewImage")
            }
        }
    }
}

PopView 还支持导航回多个级别,你可以指定要返回的数量。

PopView("Go Back Two Views", amount: 2)

// or

PopView(2) {
    Image("BackTwoViewsImage")
}

最后,PopView 还支持上述所有高级导航。 通过将数量替换为 PopType。 wiki 中将对这些不同的 PopTypes 进行完整描述。 但这是一个关于如何实现它以返回到根视图的示例。

PopView("Back To Root", popType: .root)

// or

PopView(.root) {
    Image("BackToRootImage")
}

使用编程式向后导航

使用 Navigation Router 进行编程式导航几乎与使用 PopView 一样简单。 我们只需要一个额外的步骤。 我们需要手动访问我们的 Router。 我们可以使用 @NavRouter 属性包装器来实现。

 struct ViewTwo: View {
     
     // You can name this variable whatever, router is what we will use for these examples.
     @NavRouter var router
     
     var body: some View {
         // View Body...
     }
 }

现在我们可以访问我们的 Router,我们可以用它来导航。 要弹出一个视图,你只需要调用其中一个 pop 函数。 通常你可能想在 ButtononTapGesture 中执行此操作; 但是,只要你有权访问 Router,就可以在需要的任何地方调用它。

 var body: some View {
     Button("Navigate Back One View") {
         router.pop()
     }
 }

你还可以指定要返回多个 Views,方法是将数字传递到 pop 函数中。

// Pops Back 2 Views
router.pop(2)

与 PopView 类似,你可以访问上面提到的所有高级导航方法。 你可以在应用程序文档或 Wiki 中找到这些方法。