在 SwiftUI 中,sheet 是一个用于呈现模态视图(Modal View)的修饰器,它会在当前视图上层弹出一个新的视图。sheet 通常用于临时性任务(如登录、设置、详情展示等),用户完成操作后可以关闭它返回原视图。
基本语法
swift
.sheet(isPresented: Binding<Bool>, onDismiss: (() -> Void)?, content: () -> View)
参数说明
| 参数 | 说明 |
|---|---|
isPresented |
一个 Binding<Bool>,控制 sheet 是否显示 |
onDismiss |
可选闭包,在 sheet 关闭时调用 |
content |
返回要显示的视图 |
1. 基本使用
swift
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("显示 Sheet") {
showSheet.toggle() // 触发显示/隐藏
}
.sheet(isPresented: $showSheet) {
Text("这是弹出的 Sheet 内容")
.padding()
}
}
}
效果 :点击按钮后,从底部弹出 Text 视图,点击空白处或下滑可关闭。
2. 传递数据到 Sheet
通常结合 @State 或 @ObservedObject 传递数据:
swift
struct ContentView: View {
@State private var showSheet = false
@State private var sheetData = "Hello, Sheet!"
var body: some View {
Button("显示带数据的 Sheet") {
showSheet.toggle()
}
.sheet(isPresented: $showSheet) {
SheetView(data: sheetData)
}
}
}
struct SheetView: View {
let data: String
var body: some View {
VStack {
Text(data)
.font(.title)
Button("关闭") {
// 通过环境变量或回调关闭
}
}
.padding()
}
}
3. 通过 item 绑定动态数据
如果 sheet 内容依赖动态数据(如从列表中选择一项),可以用 sheet(item:):
swift
struct User: Identifiable {
let id = UUID()
let name: String
}
struct ContentView: View {
@State private var selectedUser: User? // 必须是 Optional + Identifiable
var body: some View {
Button("显示用户 Sheet") {
selectedUser = User(name: "张三")
}
.sheet(item: $selectedUser) { user in
Text("用户名: \(user.name)")
.padding()
}
}
}
说明:
item必须是Optional且符合Identifiable,当item变为nil时,sheet自动关闭。
4. 控制 Sheet 的关闭
方法 1:使用 presentationMode(iOS 13-15)
swift
import SwiftUI
struct SheetView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
Button("关闭 Sheet") {
presentationMode.wrappedValue.dismiss()
}
}
}
方法 2:使用 dismiss(iOS 15+)
swift
struct SheetView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
Button("关闭 Sheet") {
dismiss()
}
}
}
5. 结合 onDismiss 执行回调
swift
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("显示 Sheet") {
showSheet.toggle()
}
.sheet(isPresented: $showSheet, onDismiss: {
print("Sheet 已关闭")
}) {
Text("这是 Sheet 内容")
}
}
}
6. 自定义 Sheet 样式
默认 sheet 是 iOS 系统样式,但可以调整:
-
禁止下滑关闭 (iOS 16+):
swift.presentationDetents([.medium, .large]) .interactiveDismissDisabled() // 禁止手势关闭 -
调整高度 (iOS 16+):
swift.sheet(isPresented: $showSheet) { Text("半高 Sheet") .presentationDetents([.height(200)]) }
常见问题
1. sheet 不显示?
- 确保
isPresented是@State或@Binding。 - 确保
sheet修饰器应用在正确的视图上。
2. 如何传递回调?
- 使用闭包或
@Binding让sheet能回调父视图。
3. 如何避免多次创建 sheet?
- SwiftUI 默认会缓存
sheet内容,但复杂逻辑建议用onAppear优化。
总结
| 功能 | 方法 |
|---|---|
| 基本弹窗 | .sheet(isPresented:) |
| 动态数据弹窗 | .sheet(item:) |
| 关闭 Sheet | presentationMode.dismiss() 或 dismiss() |
| 回调处理 | onDismiss |
| 禁止手势关闭 | interactiveDismissDisabled() |
| 调整高度 | presentationDetents |
sheet 是 SwiftUI 中最常用的弹窗方式,适合临时任务、表单填写等场景。