GSRouting

一个轻量级的 Swift Package,用于改进不同类型的 Sheet 和导航目的地的呈现方式,以及在选项卡之间导航的方式。

入门

步骤 1:使用 RoutableTabView

RoutableTabView 允许在 TabBar 中进行选项卡之间的程序化导航。

@main
struct AppView: App {
    
    var body: some Scene {
        WindowGroup {
            // Use `RoutableTabView` at the root of the app in the `@main` view.
            // Initialise it by passing in an array of routes, in the order you wish them to be displayed.
            RoutableTabView(tabs: [
              HomeTabRoute(),
              SettingsTabRoute()
            ])
        }
    }
}

创建一个 TabRoute

一个符合 TabRoute 协议的对象代表一个单独的选项卡,提供函数来渲染显示在选项卡栏中的标签,以及选择选项卡时显示的内容。

注意: makeLabelmakeContent 函数在选项卡状态更改时被调用,因此可以执行诸如在选择/取消选择时更改选项卡图标等操作。

重要提示: 建议在每个选项卡的 makeContent 函数中使用 .routable() 修饰符,这使得导航可以在其子视图中工作。

struct HomeTabRoute: TabRoute {
    let id: String = "home"
    
    func makeLabel(context: Context) -> some View {
        Label("Home", systemImage: context.isSelected ? "house.fill" : "house")
    }
    
    func makeContent(context: Context) -> some View {
        HomeContainerView().routable()
    }
}

步骤 2:导航到 & 呈现视图。

所有导航操作都可以通过与注入的 AppNavigationRouter 实例交互来执行。这可以通过 SwiftUI 视图中标记有 @Router 的属性来完成。

重要提示: 重要的是父视图应用 .routable() 修饰符,该修饰符注入路由器并启用导航功能。

@Router 的使用

struct MyViewSomewhereInTheApp: View {
    @Router private var router

    var body: some View {
      VStack {
        Button("Go to next page") {
         router.push(.anotherPage)
        }

        Button("Present a sheet") {
         router.push(.someSheet)
        }

        Button("Go back 1 page") {
         router.pop()
        }

        Button("Go back to start") {
         router.popToRoot()
        }

        Button("Present full screen cover") {
         router.presentCover(.someCover)
        }

        Button("Go to settings tab") {
         router.switchTab(id: "settings")
        }
      }
    }
}

创建一个 ViewRoute 用于呈现/导航

ViewRoute 声明允许呈现并导航到其 makeBody 函数中返回的视图。ViewRoute 被传递到路由器上的函数,例如 push(_:), presentSheet(_:) 等。

struct MyViewRoute: ViewRoute {
    func makeBody(context: Context) -> some View {
      MyView()
    }
}

为了方便起见,可以扩展 ViewRoute 以将路由声明为属性,这样 XCode 将在输入时出现的自动完成窗口中建议我们的自定义 ViewRoute

extension ViewRoute where Self == MyViewRoute {
   var myView: Self { .init() }
}

这使得以下语法可以工作

router.push(.myView)