Swift 可组合呈现 (Composable Presentation)

Swift v5.7 platforms iOS, macOS

为使用 ComposableArchitecture 构建的 SwiftUI 应用程序提供呈现和导航辅助工具。

📝 描述

如果您熟悉 ComposableArchitecture,您就应该知道如何从隔离的组件构建一个功能齐全的应用程序。您可以通过组合 reducer 和作用域 store 来实现。但是,当一个组件可选地嵌入另一个组件(或者意味着在导航中呈现)时,正确处理副作用可能会变得棘手。

ComposablePresentation 是一个库,它有助于在用 ComposableArchitecture 构建的应用程序中组合 reducer。 每当您需要有条件地呈现一个组件时,都可以使用它,例如呈现 sheet、在屏幕之间导航或显示组件列表。它还附带了 SwiftUI 辅助工具,用于 sheet、导航链接、for-each-store 和其他呈现方式。

.presenting 高阶 reducer 允许将 reducer 与可选呈现组件的 reducer 组合。一旦组件被解除 (其可选状态从有效值变为 nil),其 reducer 返回的 effect 将自动取消。

有关该概念的更多信息,请参见文章:SwiftUI 导航的思考

🏛 项目结构

ComposablePresentation (Xcode Workspace)
 ├─ swift-composable-presentation (Swift Package)
 |   └─ ComposablePresentation (Library)
 └─ Example (Xcode Project)
     └─ Example (iOS Application)

📖 用法

使用 Swift Package ManagerComposablePresentation 添加为项目的依赖项。

此存储库包含一个使用 SwiftUI 和 ComposableArchitecture 构建的 iOS 应用程序示例。

➡️ Sheet 示例

SwiftUI 示例,展示了如何使用具有可选状态的 store 驱动的内容呈现 sheet。 当 store 的状态具有有效值时,该 sheet 会呈现,并在变为 nil 时解除。 当 sheet 被解除时,store 的 reducer 在内容呈现期间产生的所有 effect 都会被取消。

➡️ 全屏覆盖示例

SwiftUI 示例,展示了如何使用具有可选状态的 store 驱动的内容呈现全屏覆盖。 当 store 的状态具有有效值时,该覆盖会呈现,并在变为 nil 时解除。 当覆盖被解除时,store 的 reducer 在内容呈现期间产生的所有 effect 都会被取消。

➡️ 导航目标示例

使用 .navigationDestination 的 SwiftUI 示例,由具有可选状态的 store 驱动。 当 store 的状态具有有效值时,链接处于活动状态,并在变为 nil 时变为非活动状态。 当目标被解除时,store 的 reducer 在内容呈现期间产生的所有 effect 都会被取消。

➡️ ForEachStore 示例

具有组件列表的 SwiftUI 示例。 从列表中删除组件时,其 reducer 产生的所有 effect 都会被取消。

➡️ Pop-to-root 示例

SwiftUI 示例,展示了如何在状态驱动的导航中一次性解除多个导航链接(弹回根视图)。 呈现的 store 的 reducer 产生的所有 effect 都会在解除时被取消。

➡️ 重放非 nil 状态

在大多数情况下,呈现具有相应的呈现和解除动画。 当我们使用可选状态驱动它时,就会出现问题。 假设我们要以编程方式解除 sheet,因此我们将其状态设置为 nil。 它会触发解除动画,但由于我们的状态已经是 nil,因此我们无法在此过渡期间呈现 sheet 内容。 作为一种解决方法,ComposablePresentation 提供了 replayNonNil 函数,该函数可以传递给 NavigationLinkWithStoreView.sheetView. popover 和其他 SwiftUI 辅助函数的可选 mapState 参数。

➡️ SwitchStore 示例

一个组件的 SwiftUI 示例,该组件有条件地呈现两个子组件之一。 该状态建模为一个具有两种情况的枚举。 当子组件从父组件中删除时,子组件产生的所有 effect 都会被取消。

➡️ 目标示例

一个组件的 SwiftUI 示例,该组件呈现一个互斥的目标。 目标由一个可选的枚举 case 表示。 每个 case 都使用不同的导航模式(导航链接、sheet、alert 等)呈现。 当目标被解除或更改时,呈现的组件产生的所有 effect 都会被取消。 这种导航建模设计灵感来自 Point-Free 的“Modern SwiftUI”视频系列

▶️ Deeplink 示例

使用此库组合的导航由声明性状态驱动。 这使得处理 deep link 并导航到应用程序的任何屏幕变得容易。 应用了一些解决方法来修复 SwiftUI 导航问题(这仅仅是因为 swiftui-navigation 库 by Point-Free)。 更改 Example/App.swift 中的初始状态,以便在应用程序启动时导航到任何屏幕。

▶️ NavigationStack 示例

使用 Store 驱动 NavigationStack 的 SwiftUI 示例。 该状态提供了一个可识别的目标状态数组,其索引构成导航路径。 当数组发生变异时,就会发生导航。 此示例需要 iOS ≥ 16。

🛠 开发

☕️ 您喜欢这个项目吗?

Buy Me A Coffee

📄 许可证

Copyright © 2021 Dariusz Rybicki Darrarski

许可证:MIT