我知道之前曾有人问过这个问题。不知道这在SwiftUI的Beta 4中是否已更改/取消,但是我似乎无法获得isPresented
解决方案来消除sheet
所示的模式。
这是我尝试过的简单示例,我认为这可以解决问题,但是单击“关闭”没有任何作用,当我检查self.isPresented?.value
时,它就是nil
。
struct DetailView: View {
@Environment(\.isPresented) var isPresented: Binding<Bool>?
var body: some View {
Button(action: {
self.isPresented?.value = false
}) {
Text("Close")
}
}
}
struct ContentView: View {
@State private var showingModal = false
var body: some View {
Button(action: {
self.showingModal = true
}) {
Text("Show detail")
}.sheet(isPresented: $showingModal) {
DetailView()
}
}
}
根据建议进行更新,此方法有效。似乎我手头上藏着太多书,希望它能得到更新。
struct DetailView: View {
@Binding var showingModal: Bool
var body: some View {
Button(action: {
self.showingModal = false
}) {
Text("Close")
}
}
}
struct ContentView: View {
@State private var showingModal = false
var body: some View {
Button(action: {
self.showingModal = true
}) {
Text("Show detail")
}.sheet(isPresented: $showingModal) {
DetailView(showingModal: self.$showingModal)
}
}
}
答案 0 :(得分:7)
测试版6
使用presentationMode
中的@Environment
。
struct SomeView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Text("Ohay!")
Button("Close") {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
答案 1 :(得分:1)
在当前视图中,将State bool设置为false,并将绑定传递到sheet
调用中。要显示,请将其设置为true
。还要将绑定传递到第二个视图中,以便在那里的按钮可以再次将其设置为false
。
struct ContentView : View {
@State var showSheet = false
var body: some View {
Button("Show Sheet") {
self.showSheet.toggle()
}.sheet(isPresented: self.$showSheet) {
Modal(isPresented:self.$showSheet)
}
}
}
struct Modal : View {
@Binding var isPresented : Bool
var body: some View {
Button("Done", action: {self.isPresented = false})
}
}
答案 2 :(得分:1)
一个更整洁的解决方案可能是定义一个回调函数:
struct DetailView: View {
var dismiss: () -> ()
var body: some View {
Button(action: dismiss) {
Text("Close")
}
}
}
struct ContentView: View {
@State private var showingModal = false
var body: some View {
Button(action: {
self.showingModal = true
}) {
Text("Show detail")
}.sheet(isPresented: $showingModal) {
DetailView(dismiss: { self.showingModal = false })
}
}
}
相对于额外簿记的好处在于,DetailView
不再需要知道它是一种模式,可以在不同的上下文中使用它。此外,您保留所有用于在原始视图中显示和消除模式的相关代码。
现在,无论使用哪种方法消除模态,您都应该警惕,模态仍然非常容易出错,即使在beta 6中也是如此。在各种情况下,我浪费了太多时间,这些解决方案都无法按需工作:
Button
中的ContentView
放在List
(或ScrollView
内时,因为List
只是ScrollView
的一种特殊类型),则该按钮仅一次起作用。您可以显示模态并关闭它,但是您将无法再次显示它... NavigationView
并将Button
添加到.navigationBarItems
时,您将能够根据需要频繁显示模态。但是,DetailView
中的“关闭”按钮将无法工作... 到目前为止,在这些情况下,我无法使关闭按钮正常工作。这极大地限制了现实生活中应用程序中模态的使用。 GM很有可能会解决此问题,但是请注意这些问题,直到已知它们已解决为止。
答案 3 :(得分:1)
另一种解决方案是在您的SwifUI视图中添加一个delegate
属性,该属性会将dismiss操作传递回演示者。
protocol MySwiftUIViewDelegate: class {
func myDismissAction()
}
struct MySwiftUIView {
weak var delegate: MySwiftUIViewDelegate?
var body: some View {
Button("Dismiss") {
self.delegate?.myDismissAction()
}
}
}
class MyViewController: UIViewController, MySwiftUIViewDelegate {
func presentMyView() {
var myView = MySwiftUIView()
myView.delegate = self
let hostingViewController = UIHostingController(rootView: myView)
present(vc, animated: true, completion: nil)
}
// MARK: - MySwiftUIViewDelegate
func myDismissAction() {
dismiss(animated: true)
}
}
虽然这看起来有些令人费解,但最好还是让主持人负责处理撤消,这样视图不必知道它是如何呈现的(例如,push与modal),从而使您代码更具模块化。另外,您可能需要其他委托方法,具体取决于您正在处理的内容,因此您可能已经拥有委托协议。而且,当您关闭视图时,它为您提供了执行任何其他代码的便利位置。
(尽管请记住,根据模式呈现方式/设置的不同,用户可能还可以通过向下拉视图来关闭它。)