我有一个 SwiftUI 视图,包裹在
UIHostingController
中,并在 iPad 上以 formSheet
的形式呈现。我有一个完成按钮可以关闭,并且有一个从父视图控制器传递的回调闭包,以便在按下此完成按钮时执行操作。问题发生在 iPad 上,用户可能在视图之外点击,视图被关闭,从而错过了回调。
解决此问题的一种方法是在 SwiftUI 视图的
onDismiss
中触发回调闭包。虽然它有效,但我不确定它是否是正确的地方以及是否足够可靠。文档只说当“视图从屏幕上消失”时调用 onDismiss
。但是,如果我们在导航层次结构中将一个视图推到该视图的顶部,onDismiss
仍然会被调用吗?
根据你的描述,我假设你有一个像这样的 SwiftUI 视图:
struct SomeView: View {
let callback: () -> Void
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationStack {
Text("Foo")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Done") {
callback()
dismiss()
}
}
}
}
}
}
在呈现托管控制器时,您可以设置其
presentationController
的委托并实现委托方法presentationControllerDidDismiss
。例如:
@objc func somethingIsClicked() {
let host = UIHostingController(rootView: SomeView(callback: callback))
host.modalPresentationStyle = .formSheet
host.presentationController?.delegate = self
present(host, animated: true)
}
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
callback()
}
func callback() {
print("Dismissed!")
}
presentationControllerDidDismiss
将在工作表完全关闭时调用,而不是当用户“开始”关闭它时(可以使用 presentationControllerWillDismiss
检测到),因为此时用户可以改变主意并停止关闭.
正如其文档所述,当以编程方式关闭工作表时,不会调用
presentationControllerDidDismiss
,因此您仍然需要将回调传递给 SwiftUI 视图。
另请注意,您可以设置:
host.isModalInPresentation = true
强制用户使用完成按钮关闭工作表。