SwiftUI关闭模态

Ugo*_*ino 27 modal-dialog swift swiftui

由于SwiftUI是声明性的,因此没有dismiss方法。如何在上添加一个关闭/关闭按钮DetailView

struct DetailView: View {
  var body: some View {
  Text("Detail")
  }
}

struct ContentView : View {
  var body: some View {
  PresentationButton(Text("Click to show"), destination: DetailView())
  }
}
Run Code Online (Sandbox Code Playgroud)

Mo *_*ani 40

您可以presentationMode在模态视图中使用环境变量并调用self.presentaionMode.wrappedValue.dismiss()以消除模态:

struct ContentView: View {

  @State private var showModal = false

  var body: some View {
    Button(action: {
        self.showModal = true
    }) {
        Text("Show modal")
    }.sheet(isPresented: self.$showModal) {
        ModalView()
    }
  }
}


struct ModalView: View {

  @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

  var body: some View {
    Group {
      Text("Modal view")
      Button(action: {
         self.presentationMode.wrappedValue.dismiss()
      }) {
        Text("Dismiss")
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  • 如果使用列表问题,我也会体验到Beta 3“仅呈现一次”。但是,在某些情况下,Beta 4似乎破坏了Modal使用isPresented环境var退出自身的功能。上面的示例仍然有效,但我的示例无效。我仍在尝试找出问题所在。 (4认同)
  • 我注意到在“Xcode Version 11.0 (11A419c)”中,当使用“self.presentationMode.wrappedValue.dismiss()”时,“.sheet(”上的“onDismiss”函数不会被调用。当我关闭模态视图时通过下拉回调被调用。 (3认同)
  • 您也可以只使用“@Environment(\.presentationMode) varpresentationMode”,因为 Swift 将通过指定的键路径推断类型。 (2认同)
  • 这是错误的。您应该传递一个也用于 isPresented 的状态变量,而不是弄乱presentationMode。 (2认同)

thi*_*ezn 27

在 Xcode Beta 5 中,另一种方法是在启动模态的视图中使用 @State,并在模态视图中添加绑定以控制模态的可见性。这不需要您进入@EnvironmentpresentationMode 变量。

struct MyView : View {
    @State var modalIsPresented = false

    var body: some View {
        Button(action: {self.modalIsPresented = true})  {
            Text("Launch modal view")
        }
        .sheet(isPresented: $modalIsPresented, content: {
            MyModalView(isPresented: self.$modalIsPresented)
        })
    }
}


struct MyModalView : View {
    @Binding var isPresented: Bool

    var body: some View {
        Button(action: {self.isPresented = false})  {
            Text("Close modal view")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您通过声明式方法和单一事实来源遵守 SwiftUI 的原则 (4认同)
  • 它只在第一次起作用,如果我关闭并再次尝试打开窗口,它就不再起作用了。 (2认同)

小智 13

这是一种消除呈现视图的方法。

struct DetailView: View {
    @Binding
    var dismissFlag: Bool

    var body: some View {
        Group {
            Text("Detail")
            Button(action: {
                self.dismissFlag.toggle()
            }) {
                Text("Dismiss")
            }
        }

    }
}

struct ContentView : View {
    @State var dismissFlag = false

    var body: some View {
        Button(action: {
            self.dismissFlag.toggle()
        })
        { Text("Show") }
            .presentation(!dismissFlag ? nil :
                Modal(DetailView(dismissFlag: $dismissFlag)) {
                print("dismissed")
            })
    }
}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


Tom*_*ARD 9

Swift 5.5 和 SwiftUI 3 中的新增功能:

@Environment(\.dismiss) var dismiss
Run Code Online (Sandbox Code Playgroud)

然后在函数或主体代码中的某个位置,只需调用:

self.dismiss()
Run Code Online (Sandbox Code Playgroud)


Tom*_*m P 8

似乎对于Xcode 11 Beta 7(在Xcode的版本11M392r上)来说,它略有不同。

@Environment(\.presentationMode) var presentation


Button(action: { self.presentation.wrappedValue.dismiss() }) { Text("Dismiss") }
Run Code Online (Sandbox Code Playgroud)


小智 7

您可以实现这一点。

struct view: View {
    @Environment(\.isPresented) private var isPresented

    private func dismiss() {
        isPresented?.value = false
    }
}
Run Code Online (Sandbox Code Playgroud)


Chu*_*k H 6

Beta 5中现在有一种非常干净的方法来执行此操作。

import SwiftUI

struct ModalView : View {
    // In Xcode 11 beta 5, 'isPresented' is deprecated use 'presentationMode' instead
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    var body: some View {
        Group {
            Text("Modal view")
            Button(action: { self.presentationMode.wrappedValue.dismiss() }) { Text("Dismiss") }
        }
    }
}

struct ContentView : View {
    @State var showModal: Bool = false
    var body: some View {
        Group {
            Button(action: { self.showModal = true }) { Text("Show modal via .sheet modifier") }
                .sheet(isPresented: $showModal, onDismiss: { print("In DetailView onDismiss.") }) { ModalView() }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在什么情况下是错误的?您的问题是正确性问题还是风格偏好问题?还有多种其他方法可以完成相同的任务,而且效果也一样。Apple 自己的 iOS 13 发行说明将此记录为一种消除 Modals 的方法,并且它确实有效。谢谢。 (5认同)

Moj*_*ini 6

如果进入则自动弹出,如果进入Navigation则自动关闭Modal


只需presentationMode从目标视图中的环境中dismiss获取wrappedValue

struct DestinationView: View {
    @Environment(\.presentationMode) private var presentationMode

    var body: some View {
        Button("Dismiss") {
            self.presentationMode.wrappedValue.dismiss()
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

演示(弹出/关闭)

流行音乐 解雇

  • 感谢您发布此内容。这就是为什么“PresentationMode”可能不是关闭模式的最佳解决方案,因为如果您有“NavigationView”,它可能会弹出到上一个视图。如果你想确保关闭模式,那么你应该传递一个“@State”变量。 (2认同)

paw*_*222 6

iOS 15

而不是presentationMode我们现在可以使用DismissAction.

这是文档中的一个示例:

struct SheetView: View {
    @Environment(\.dismiss) var dismiss

    var body: some View {
        NavigationView {
            SheetContents()
                .toolbar {
                    Button("Done") {
                        dismiss()
                    }
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 对于 iOS 15 来说,这是一种很好而简洁的方法。不过,我认为 - 由于大多数答案都提供了利用“@State”或“@Environment”的解决方案,恕我直言,这在大多数用例中都不是正确的方法。当模态呈现到视图中时,这种方法会改变逻辑。视图中的逻辑?恕我直言,更好的方法是利用“视图模型”或执行逻辑的类似事物。在模态的情况下,它只是提供适当的“视图状态”,它清楚地定义何时显示模态、何时不显示模态,并且还处理“关闭”操作(由用户发起的函数调用)而不是视图 (2认同)
  • @CouchDeveloper 恕我直言,这是一个糟糕的建议,完全违背了苹果自己的指导和指示。SwiftUI 视图既是视图又是视图模型,除了看起来很忙并且徒劳地使文件数量增加一倍之外,绝对没有理由将两者分开。苹果构建状态、绑定、环境对象等以在 swiftui 视图本身中使用是有原因的。请随时搜索 Apple 自己的开发者论坛以获取更深入的说明 (2认同)