Alert 是一种强制回应视图。当它出现时,整个画面会被锁住。如果你不点击上面的任何一个选项,你无法做接下来的动作。
// 参数弹窗标题,字符串
.alert("Important message", isPresented: $showingAlert) {
Button("OK") { }
}
// 参数,是弹窗按钮视图的闭包
.alert("Important message", isPresented: $showingAlert) {
Button("OK") { }
// Button 后面如果是空的闭包,这意味着没有设置任何在按下按钮时运行的功能
// 这不重要,因为点击 Alert 中的任何按钮都会自动关闭 Alert 弹窗,不需要自己设置
// 如果有任何额外的功能需要添加,就加到 button 的闭包中
}
// Alert 弹窗最多可以添加 2 个按钮,不能再多
// 并且最好添加按钮的角色,以确保每个按钮的作用一目了然
.alert("Important message", isPresented: $showingAlert) {
Button("Delete", role: .destructive) { }
Button("Cancel", role: .cancel) { }
}
// 还可以在窗口内添加消息文本,以在标题旁边加上第二个尾随尾部 message,如下所示:
Button("Show Alert") {
showingAlert = true
}
.alert("Important message", isPresented: $showingAlert) {
Button("OK", role: .cancel) { }
} message: {
Text("Please read this.")
}
// 两个闭包一起设置
.alert( ... )
//第1个闭包:设置按钮
{
//除了上面一个例子的设置方式,还可以让系统提供默认的“确定”按钮,_ in代表不需要任何按钮
_ in
}
//第2个闭包:设置说明文字
message: {
facility in
Text(facility.description)
}
// 使用 isPresent 双向数据绑定状态属性的布尔值。
// 绑定后,程序将监视该布尔值 ,一旦它为真就会显示弹窗;
.alert("Important message", isPresented: $showingAlert) {
Button("OK") { }
}
// 为什么要双向绑定?因为当弹窗被关闭时,布尔值会自动设回 false
使用 presenting
绑定可选值,其关键是使用 optional
的、符合 Identifiable
协议的对象作为显示 alert
的条件,并且闭包提供了用于该条件的非可选值,因此可以安全地使用它。
// 1. 首先创建一个符合 Identifiable 协议的简单 User 结构
struct User: Identifiable {
var id = "Taylor Swift"
}
// 2. 然在 ContentView 内创建一个属性来跟踪选择的用户,默认设置为 nil
@State private var selectedUser: User? = nil
@State private var isShowingUser = false
// 3. 需要同时传递【布尔值】和【可选值】,这样可以在需要时显示弹窗,也可以通过可选值进行解包
Text("Hello, World!")
.onTapGesture{
// 如果只保留布尔值这一行代码,也是能呈现 alert 的,只是获取不到可选值的数据了
isShowingUser = true
// 如果只保留可选值赋值这一句代码,无法呈现 alert
selectedUser = User()
}
.alert(
"Welcome",
isPresented: $isShowingUser,
presenting: selectedUser
){
//成功获取解包后的 user
user in
Button(user.id){}
}
// 加上 Message 参数的写法
.alert("Delete Project", isPresented: $reconfirmDialog, presenting: projectToDelete, actions: { project in
Button("Delete", role: .destructive) { removeProject(project) }
Button("Cancel", role: .cancel) { }
}, message: { _ in
Text("该项目所包含的所有点子也将被删除。")
})
<aside>
💡 注意:用 Alert
绑定 optional
值的时候,必须同时传递: 控制视图展示的【布尔值】,以及 遵循 Identifiable
协议的 【可选值】。这点和 sheet
视图不一样,参见 参数:item 绑定 Optional
</aside>
Alert(title: , message: , dismissButton: )
//方式1
.alert(isPresented: $showAlert) {
() ->
Alert in
return Alert(
// 标题
title: Text("Hello there!"),
// 说明
message: Text("this is my first pop up"),
// 解除按钮样式
dismissButton: .default(Text("Awesome"))
)
}
//方式2
.alert(
isPresented: $showAlert,
content: {
Alert(
title: Text("Error"),
message: Text(self.alertMessage),
dismissButton: .default(Text("OK"))
)
}
)
Alert(title: , message: , primaryButton: , secondaryButton:)
//省略掉闭包的参数
.alert(isPresented: $showAlert) {
Alert(
title: Text("..."),
message: Text(alertMessage),
primaryButton: .default(Text("Yes"),
action: {
self.presentationMode.wrappedValue.dismiss() }
),
secondaryButton: .cancel(Text("No"))
)
}
.alert("Welcome", isPresented: $isShowingUser) { }
//当它运行时,你会看到一些有趣的东西:尽管没有明确指定“确定”按钮,但结果与以前完全相同
//SwiftUI 发现警报中没有任何操作,因此它添加了一个默认操作,标题为“OK”,并且在点击时会关闭警报
如果您尝试将多个 alert()
修饰符附加到单个视图,您会发现您的代码无法按预期工作(一个警报可以工作,但另一个则不行)。
要解决此问题,您需要确保为每个视图附加不超过一个 alert()
修饰符。记住:您不需要将警报附加到同一视图,您可以将它们附加到任何地方。事实上,您会发现将它们直接附加到显示它们的东西(例如按钮)最适合。
SwiftUI 使用 confirmationDialog()
修饰符向用户显示一系列选项。之前的 ActionSheet
在 iOS14 已被 confirmationDialog
代替。如果您的目标是 iOS 14 之前版本,则需要使用 ActionSheet
。但如果目标是 iOS 15 版本,或者想支持 macOS,则应该使用 confirmationDialog()
。
SwiftUI 提供了 alert()
来呈现重要的选择;提供了 sheet()
来在当前视图之上呈现整个视图;它也提供了 confirmationDialog()
,一种可以添加许多按钮的替代方案 。它是一个从屏幕底部向上滑动的按钮列表,您可以添加任意数量的按钮,它甚至可以滚动。
从创建方式上看,confirmationDialog
和 Alert
几乎相同:
从视觉上看,confirmationDialog
和 Alert
非常不同:
Alert
出现在屏幕中央,必须通过选择按钮主动关闭;confirmationDialog
从底部向上滑动,可以包含大量按钮,并且可以通过选择按钮、点击取消、点击选项外部来关闭;.confirmationDialog("Change background", isPresented: $showingConfirmation) { ... }
// 标题显示或隐藏
.confirmationDialog("Change background", isPresented: $showingConfirmation, titleVisibility: .visible) { ... }
.confirmationDialog("Change background", isPresented: $showingConfirmation) {
...
} message: {
Text("Select a new color")
}
//除了提供一个标题,还可以选择附加一条消息。按钮按照提供的顺序垂直堆叠在屏幕上,通常最好在末尾添加一个取消按钮。虽然可以通过点击屏幕上的其他位置来取消,但最好为用户提供明确的说明选项。
@State private var showingConfirmation = false
// 绑定状态属性:决定对话框当前是否显示
.confirmationDialog("Change background", isPresented: $showingConfirmation) { ... }
// 按钮是按照提供的顺序垂直堆叠在屏幕上,通常最好在末尾添加一个取消按钮
// 虽然可以通过点击屏幕上的其他位置来取消,但最好为用户提供明确的说明选项
.confirmationDialog("Change background", isPresented: $showingConfirmation) {
Button("Red") { backgroundColor = .red }
Button("Green") { backgroundColor = .green }
Button("Blue") { backgroundColor = .blue }
Button("Cancel", role: .cancel) { }
} message: {
Text("Select a new color")
}
完整例子:
@State private var showingConfirmation = false
.confirmationDialog("Change background", isPresented: $showingConfirmation) {
Button("Red") { backgroundColor = .red }
Button("Green") { backgroundColor = .green }
Button("Blue") { backgroundColor = .blue }
Button("Cancel", role: .cancel) { }
} message: {
Text("Select a new color")
}
// 因为这个新的 API 更加灵活,实际上可以使用 ForEach 将这些操作折叠成一个简单的循环:
struct ContentView: View {
@State private var showingOptions = false
@State private var selection = "None"
var body: some View {
VStack {
Text(selection)
Button("Confirm paint color") {
showingOptions = true
}
.confirmationDialog("Select a color", isPresented: $showingOptions, titleVisibility: .visible) {
ForEach(["Red", "Green", "Blue"], id: \\.self) { color in
Button(color) {
selection = color
}
}
}
}
}
}