记录一个状态值,操作触发状态值的改变进而引发弹出动作
Modal
.sheet(isPresented: <Binding<Bool>>, content: <() -> View>)
// 如果仅在当前页面管理,则只需要声明成 @State 即可
@State var isModal = false
var body: some View {
// ...
Button("Modal") {
// 改变状态值
isModal = true
}.sheet(isPresented: self.$isModal) {
modalView()
}
}
dimiss
法一:标志位传递
在内页中声明 @Binding var isModal: Bool
,将外部标志位 isModal 传递到内页,内页操作触发标志位改变,引发界面刷新
法二:block(推荐)
在内页声明 @State var closeActionBlock: (()->())?
,按钮点击时抛出事件让外部响应,改变标志位触发界面刷新
Button("Modal") {
// 改变状态值
isModal = true
}.sheet(isPresented: self.$isModal) {
modalView {
self.$isModal = false
}
}
法三:使用环境变量进行页面的自我管理
内页自我管理:
// iOS13:
@Environment (\.presentationMode) var presentationMode
Button("dimiss me") {
presentationMode.wrappedValue.dismiss()
}
// iOS15:
@Environment (\.dismiss) var dismiss
Button("dismiss me") {
dismiss()
}
不过这种方法需要注意几点:
消失整个界面的时候,只能引出来的界面(例如NavigationView或者弹出的Alert、Sheet、Popover),不然
.presentationMode.wrappedValue.isPresented
的值是 false,自然无法dismiss()
。弹出的Alert、Sheet或者Popover之类的,使用这个方法消失的是激活弹出的那个界面,而不是弹出之后的界面。
Alert
.alert(isPresented: <Binding<Bool>>, actions: <() -> View>)
@State var isAlert = false
var body: some View {
// ...
Text("Tap")
.onTapGesture {
// 改变状态值
isAlert = true
}.alert(isPresented: self.$isAlert) {
Alert(
title: Text("Title"),
message:Text("message"),
primaryButton:
Alert.Button.default(Text("cancel")),
secondaryButton:
Alert.Button.default(Text("copy"), action:{
UIPasteboard.general.string = "hello world"
})
)
}
}
.alert<Item>(item: Binding<Item?>, content: (Item) -> Alert) -> some View where Item : Identifiable
alert(item:content:) 接受一个 Identifiable? 的绑定,当这个绑定值不为 nil 时,显示一个弹框。
.alert(item: settingsBinding.loginError) { error in
Alert(title: Text(error.localizedDescription))
}
enum AppError: Error, Identifiable {
var id: String { localizedDescription }
case passwordWrong
}
extension AppError: LocalizedError {
var localizedDescription: String {
switch self {
case .passwordWrong: return "密码错误"
}
}
}