繁体   English   中英

如何从 SwiftUI 中的任何视图显示弹出窗口

[英]How to show popup from any view in SwiftUI

我正在使用 swiftui 并且正在开发大型应用程序。 我有太多的视图,但我想显示一个可以从应用程序内的任何视图弹出的视图。 我几乎不可能在每个 view.swift 上放置“.sheet”或“@State isPopUpShowing”。

有没有办法在不弄乱每个视图文件的情况下对我的弹出窗口进行一次/在一个文件中编码?

您可以注入一个ObservableObject来管理视图层次结构根中的工作表(在我的示例中为ContentView )并通过使用.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")
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM