如何检查 SwiftUI 视图是否以模态方式呈现或推送到导航堆栈上?

Tru*_*an1 1 swiftui

我试图仅在以模态方式呈现时才在视图上有条件地显示自定义按钮。这可以在 UIKit 中完成,但我正在尝试在 SwiftUI 中完成此操作。

我尝试使用环境变量presentationMode来检查它是否正在显示,但在这两种情况下标志都是 true:

@Environment(\.presentationMode) private var presentationMode

if presentationMode.wrappedValue.isPresented { // true in both cases
   ...
}
Run Code Online (Sandbox Code Playgroud)

有没有办法让视图知道它是否正在呈现或是否已推送?

额外上下文:

我正在尝试创建一个自定义修改器,它将自动在这两种情况下重用的视图上添加一个关闭按钮:

struct OverlayDismissButtonModifier: ViewModifier {
    @Environment(\.presentationMode) private var presentationMode

    func body(content: Content) -> some View {
        content
            .overlay(
                Group {
                    if presentationMode.wrappedValue.isPresented { // <-- True in both cases :(
                        Button(action: { presentationMode.wrappedValue.dismiss() }) {
                            Label(LocalizedStringKey("Close"), systemImage: "xmark")
                                .labelStyle(IconOnlyLabelStyle())
                                .foregroundColor(Color(.label))
                                .padding(8)
                                .background(
                                    Circle()
                                        .fill(Color(.systemBackground).opacity(0.8))
                                )
                        }
                        .padding([.top, .trailing])
                    }
                },
                alignment: .topTrailing
            )
    }
}

extension View {
    func overlayDismissButton() -> some View {
        modifier(OverlayDismissButtonModifier())
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 5

这对我有用。

var body: some View {
    if isPresentedModally {
        Text("Presented modally")
    } else {
        Text("Pushed onto navigation stack")
    }
}
Run Code Online (Sandbox Code Playgroud)
extension View {
    var isPresentedModally: Bool {
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
        let window = windowScene.windows.first
        else {
            return false
        }
        return window.rootViewController?.presentedViewController != nil
    }
Run Code Online (Sandbox Code Playgroud)