在 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 中最常用的弹窗方式,适合临时任务、表单填写等场景。