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

相关推荐
名字还没想好☜30 分钟前
React 实现暗黑模式切换:localStorage 持久化、SSR 首屏闪烁与跟随系统主题
前端·javascript·react.js·ecmascript·react·next.js
console.log('npc')2 小时前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
爱学堂IT分享3 小时前
Cesium可视化系统实战课程-Cesium教程学习
前端
糖墨夕3 小时前
理解大语言模型:Agent 的“大脑”
前端·agent
Rain的Java大神之路3 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发
cpolar技术支持4 小时前
浏览器也能跑本地 AI:用 Transformers.js + WebGPU 做一个最小推理 Demo,cpolar 给同事远程体验
前端·ai·cpolar·webgpu·transformers.js
计算机魔术师5 小时前
OpenAI 发布 GPT-6 Astra:多项基准刷新纪录, cybersecurity 能力达 Critical 阈值
前端
xy34535 小时前
Axure9.0中继器遮罩实现方法
前端·ui·html·axure·原型·产品设计
风骏时光牛马5 小时前
智能任务自动化协同AI工作流
前端
IT_陈寒5 小时前
Python的多线程居然是个假把式?搞清GIL让我少熬三天夜
前端·人工智能·后端