sheet在SwiftUI中的基本用法

在 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. 如何传递回调?

  • 使用闭包或 @Bindingsheet 能回调父视图。

3. 如何避免多次创建 sheet

  • SwiftUI 默认会缓存 sheet 内容,但复杂逻辑建议用 onAppear 优化。

总结

功能 方法
基本弹窗 .sheet(isPresented:)
动态数据弹窗 .sheet(item:)
关闭 Sheet presentationMode.dismiss()dismiss()
回调处理 onDismiss
禁止手势关闭 interactiveDismissDisabled()
调整高度 presentationDetents

sheet 是 SwiftUI 中最常用的弹窗方式,适合临时任务、表单填写等场景。

相关推荐
洛卡卡了1 分钟前
Sentry 都不想接,这锅还让我背?这xx工作我不要了!
前端·架构
咖啡の猫5 分钟前
Vue 实例生命周期
前端·vue.js·okhttp
JNU freshman19 分钟前
vue 之 import 的语法
前端·javascript·vue.js
剑亦未配妥20 分钟前
Vue 2 响应式系统常见问题与解决方案(包含_demo以下划线开头命名的变量导致响应式丢失问题)
前端·javascript·vue.js
凉柚ˇ23 分钟前
Vue图片压缩方案
前端·javascript·vue.js
慧一居士23 分钟前
vue 中 directive 作用,使用场景和使用示例
前端
慧一居士25 分钟前
vue 中 file-saver 功能介绍,使用场景,使用示例
前端
文心快码BaiduComate1 小时前
文心快码3.5S实测插件开发,Architect模式令人惊艳
前端·后端·架构
Kimser1 小时前
基于 VxeTable 的高级表格选择组件
前端·vue.js
摸着石头过河的石头1 小时前
JavaScript 防抖与节流:提升应用性能的两大利器
前端·javascript