ScreenNavigatorKit

框架,为在 SwiftUI 中管理导航提供便捷的环境。

优点

🔩 要求

🧐 它如何工作?!

框架只有两个 state object,每个都隔离了 @State var isActive: Bool@State var isPresent: Bool 标志的 "切换工作"。

1. NavigationStackController

UINavigationController 一样,它存储堆栈状态并使用 pushpop 方法提供堆栈转换

let navigationStackController = NavigationStackController()

// Standard usage

navigationStackController.push(Text("My View"))
navigationStackController.pop()
navigationStackController.popToRoot()

// Advanced usage

enum Screen: Hashable { 
    case detail
    ...
}

navigationStackController.push(tag: Screen.detail, DetailView())
navigationStackController.pop(to: Screen.detail)

它的伴侣是 NavigationStackView – 对 NavigationView 的包装,将其与 NavigationStackController 绑定

struct ContentView: View { 
    @StateObject var navigationStackController = NavigationStackController() 

    var body: some View { 
        NavigationStackView(navigationStackController) { 
            RootView(
                showDetails: { model in 
                    navigationStackController.push(DetailView(model: model))
                },
                showSettings: { 
                    navigationStackController.push(SettingsView())
                }
            )
        }
    }
}

// Another usage with automatic initialized NavigationStackController

struct ContentView: View { 
    var body: some View { 
        NavigationStackView { controller in
            RootView(
                showDetails: { model in 
                    controller.push(DetailView(model: model))
                },
                showSettings: { 
                    controller.push(SettingsView())
                }
            )
        }
    }
}

任何被 push 的视图都可以通过 EnvironmentObject 访问 NavigationStackViewNavigationStackController

struct DetailView: View { 
    let model: Model
    @EnvironmentObject var navigationStackController: NavigationStackController

    var body: some View { 
        VStack { 
            Text(model.title)
            Button("pop to root") { 
                navigationStackController.popToRoot()
            }
        }
    }
}

💫 额外特性: 您可以使用任何 Hashable 类型标记任何被 push 的视图。 它允许在 pop 时引用特定屏幕

navigationStackController.push(tag: "Screen 1", Screen1()))
navigationStackController.pop(to: "Screen 1")

2. ModalStackController

NavigationStackController 一样,ModalStackController 控制模态堆栈层次结构并使用 presentdismiss 方法提供堆栈转换

let modalStackController = ModalStackController()

// Standard usage

modalStackController.present(.sheet, Text("My View"))
modalStackController.present(.fullScreenCover, Text("Another View"))
modalStackController.dismiss()
modalStackController.dismissAll()

// Advanced usage

enum Screen: Hashable { 
    case detail
    ...
}

modalStackController.present(.sheet, tag: Screen.detail, DetailView())
modalStackController.dismiss(to: Screen.detail)

🚧 注意: SwiftUI 不允许一次关闭多个视图! 因此,诸如 dismissAll()dismiss(to:)/dismiss(from:) 之类的方法将依次关闭所有视图。

它的伴侣是 ModalStackView,它将 ModalStackController 与之绑定

struct ExampleApp: App { 
    @StateObject var modalStackController = ModalStackController()

    var body: some Scene { 
        WindowGroup {
            ModalStackView(modalStackController) { 
                RootView()
            }
        }
    }
}

任何呈现的视图也可以通过 EnvironmentObject 访问 ModalStackController

struct RootView: View { 
    @EnvironmentObject var modalStackController: ModalStackController

    var body: some View { 
        VStack { 
            Text("Home screen")
            Button("FAQ") { 
                modalStackController.present(.sheet, FAQView())
            }
            Button("Authorize") { 
                modalStackController.present(.fullScreenCover, LoginView())
            }
        }
    }
}

💫 就像在 NavigationStackController 中一样,您可以在使用 ModalStackController present 时标记呈现的视图

API

NavigationStackController

ModalStackController

FAQ

我可以在我的项目中将此框架与现有的导航方法混合使用吗?

可以,您可以。 该框架不影响以其他方式构建的导航,例如通过标准 @State var isActive: Bool 标志或通过 UIKit hack。
NavigationStackControllerModalStackController 创建本地状态并仅管理他们自己的状态。

Alert 呢?

不幸的是,该框架不支持使用 Alert 的这种机制,但是您可以通过类似于 ModalStackController 的方式自己实现它
您的项目可以有许多不同的自定义呈现方式(popupsnackbartoastnotifications),并且每种方式都需要特定的逻辑来处理层次结构,具体取决于它们的实现。
因此,不计划向框架添加新的呈现方法。

📦 安装

Swift Package Manager

创建一个 Package.swift 文件。

// swift-tools-version:5.3

import PackageDescription

let package = Package(
  name: "YOUR_PROJECT_NAME",
  dependencies: [
      .package(url: "https://github.com/Ernest0-Production/ScreenNavigatorKit.git", from: "0.0.3")
  ],
  targets: [
      .target(name: "YOUR_TARGET_NAME", dependencies: ["ScreenNavigatorKit"])
  ]
)

鸣谢

许可证

ScreenNavigatorKit 在 MIT 许可证下发布。 有关详细信息,请参见LICENSE