swift - 如何在 SwiftUI 中的任何视图中显示弹出窗口
问题描述
我正在使用 swiftui,并且正在开发大型应用程序。我有太多视图,但我想显示一个可以从应用程序内的任何视图中弹出的视图。我几乎不可能在每个 view.swift 上放置“.sheet”或“@State isPopUpShowing”。
有没有办法在一个文件中对我的弹出窗口进行一次编码,而不会弄乱每个视图文件?
解决方案
ObservableObject
您可以在视图层次结构的根目录中注入一个管理工作表(ContentView
在我的示例中)并通过 using 传播它.environmentObject
。然后,子视图将能够访问工作表管理器并从任何地方放置工作表。
class SheetManager : ObservableObject {
struct SheetItem : Identifiable {
var id = UUID()
var message : String
}
@Published var sheetItem : SheetItem?
@ViewBuilder func sheetForItem(item: SheetItem) -> some View {
Text(item.message)
}
func buildAndShowSheet(message : String) {
sheetItem = SheetItem(message: message)
}
}
struct ContentView: View {
@StateObject private var sheetManager = SheetManager()
var body: some View {
VStack {
Text("Hello, world!")
ChildView()
}
.sheet(item: $sheetManager.sheetItem) { item in
sheetManager.sheetForItem(item: item)
}
.environmentObject(sheetManager)
}
}
struct ChildView: View {
@EnvironmentObject private var sheetManager : SheetManager
var body: some View {
VStack {
Text("Child view that triggers sheet")
Button("Open sheet") {
sheetManager.buildAndShowSheet(message: "Sheet is open")
}
}
}
}
为了稍微高级一点,因为子视图不需要响应工作表管理器的更新,您实际上可以将其设置为自定义环境键:
private struct SheetManagerKey: EnvironmentKey {
static let defaultValue = SheetManager()
}
extension EnvironmentValues {
var sheetManager: SheetManager {
get { self[SheetManagerKey.self] }
set { self[SheetManagerKey.self] = newValue }
}
}
class SheetManager : ObservableObject {
struct SheetItem : Identifiable {
var id = UUID()
var message : String
}
@Published var sheetItem : SheetItem?
@ViewBuilder func sheetForItem(item: SheetItem) -> some View {
Text(item.message)
}
func buildAndShowSheet(message : String) {
sheetItem = SheetItem(message: message)
}
}
struct ContentView: View {
@StateObject private var sheetManager = SheetManager()
var body: some View {
VStack {
Text("Hello, world!")
ChildView()
}
.sheet(item: $sheetManager.sheetItem) { item in
sheetManager.sheetForItem(item: item)
}
.environment(\.sheetManager, sheetManager)
}
}
struct ChildView: View {
@Environment(\.sheetManager) private var sheetManager
var body: some View {
VStack {
Text("Child view that triggers sheet")
Button("Open sheet") {
sheetManager.buildAndShowSheet(message: "Sheet is open")
}
}
}
}
推荐阅读
- flask - Flask/React 应用程序,下载的二进制(pkpass)文件与服务器上的相同文件不同
- java - 计算BST高度的递归函数
- haskell - 如何使用递归方案更新结构?
- python - 如何在 Linux 上 conda 安装 openAI gym - 包冲突
- adonis.js - Adonis.js - 播种用户和配置文件引发 DB 错误 (Postgres)
- cryptography - 以这样的方式输出唯一的函数 function(A,B) = function(B,A)
- android - 自定义适配器和 ListView 崩溃
- java - URLConnection inputStream 返回“Busy”为什么?
- java - 从 SwingWorker 线程返回数组到主线程
- r - nlme 中的多重随机效应