SwiftUI:关闭模态
SwiftUI: close modal
我知道这个问题以前有人问过也有人回答过。不确定这个 changed/broke 是否在 SwiftUI 的 Beta 4 中,但我似乎无法获得 isPresented
解决方案来消除 sheet
.
显示的模态
这是我尝试过的一个简单示例,我认为这会起作用,但是单击 "Close" 没有任何反应,当我检查 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)
}
}
}
在呈现视图中,将 State 布尔值配置为 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})
}
}
Beta 6
使用 @Environment
中的 presentationMode
。
struct SomeView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Text("Ohay!")
Button("Close") {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
一个更简洁的解决方案可能是定义一个回调函数:
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 中也是如此。我在各种情况下浪费了太多时间,其中 none解决方案正常工作:
- 当你把
ContentView
中的 Button
放在 List
中(或 ScrollView
,因为 List
只是 [=15 的一种特殊类型=]) 那么这个按钮只能工作 一次。您可以显示模态并关闭它,但您将无法再次显示它...
- 当您使用
NavigationView
并将 Button
添加到 .navigationBarItems
时,您将能够随心所欲地显示模态。但是,DetailView
中的关闭按钮将不起作用...
到目前为止,我无法使关闭按钮在这些情况下正常工作。这在现实生活中的应用程序中限制了模态的使用。 GM 很有可能会修复此问题,但请注意这些问题,直到已知它们已修复。
另一种解决方案是将 delegate
属性 添加到您的 SwifUI 视图,它将关闭操作传递回演示者。
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)
}
}
虽然这看起来有点令人费解,但也可以说让演示者负责处理解雇会更好,这样视图就不必知道它是如何呈现的(例如推送与模态),因此使您的代码更加模块化。另外,您可能需要其他委托方法,具体取决于您正在处理的内容,因此您可能已经有了委托协议。当视图被关闭时,它为您提供了一个方便的地方来执行任何附加代码。
(请记住,根据模式呈现样式/设置,用户也可以通过下拉视图来关闭。)
我知道这个问题以前有人问过也有人回答过。不确定这个 changed/broke 是否在 SwiftUI 的 Beta 4 中,但我似乎无法获得 isPresented
解决方案来消除 sheet
.
这是我尝试过的一个简单示例,我认为这会起作用,但是单击 "Close" 没有任何反应,当我检查 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)
}
}
}
在呈现视图中,将 State 布尔值配置为 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})
}
}
Beta 6
使用 @Environment
中的 presentationMode
。
struct SomeView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Text("Ohay!")
Button("Close") {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
一个更简洁的解决方案可能是定义一个回调函数:
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 中也是如此。我在各种情况下浪费了太多时间,其中 none解决方案正常工作:
- 当你把
ContentView
中的Button
放在List
中(或ScrollView
,因为List
只是 [=15 的一种特殊类型=]) 那么这个按钮只能工作 一次。您可以显示模态并关闭它,但您将无法再次显示它... - 当您使用
NavigationView
并将Button
添加到.navigationBarItems
时,您将能够随心所欲地显示模态。但是,DetailView
中的关闭按钮将不起作用...
到目前为止,我无法使关闭按钮在这些情况下正常工作。这在现实生活中的应用程序中限制了模态的使用。 GM 很有可能会修复此问题,但请注意这些问题,直到已知它们已修复。
另一种解决方案是将 delegate
属性 添加到您的 SwifUI 视图,它将关闭操作传递回演示者。
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)
}
}
虽然这看起来有点令人费解,但也可以说让演示者负责处理解雇会更好,这样视图就不必知道它是如何呈现的(例如推送与模态),因此使您的代码更加模块化。另外,您可能需要其他委托方法,具体取决于您正在处理的内容,因此您可能已经有了委托协议。当视图被关闭时,它为您提供了一个方便的地方来执行任何附加代码。
(请记住,根据模式呈现样式/设置,用户也可以通过下拉视图来关闭。)