尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
swiftui-expert-skill - sheet-navigation-patterns
SwiftUI Sheet、导航与 Inspector 模式参考目录Sheet 模式导航模式使用 NavigationSplitView 的多列导航Inspector呈现修饰符汇总清单Sheet 模式项目驱动的 Sheet首选呈现基于模型的内容时使用.sheet(item:)而不是.sheet(isPresented:)。// 好 - 项目驱动StateprivatevarselectedItem:Item?varbody:someView{List(items){iteminButton(item.name){selectedItemitem}}.sheet(item:$selectedItem){iteminItemDetailSheet(item:item)}}// 避免 - 布尔标志需要单独的状态StateprivatevarshowSheetfalseStateprivatevarselectedItem:Item?varbody:someView{List(items){iteminButton(item.name){selectedItemitem showSheettrue}}.sheet(isPresented:$showSheet){ifletselectedItem{ItemDetailSheet(item:selectedItem)}}}原因.sheet(item:)自动处理呈现状态并避免在 sheet body 中进行可选解包。Sheet 自己拥有其动作Sheet 应该使用Environment(\.dismiss)在内部处理自己的关闭和动作。避免从父视图传递onSave/onCancel闭包——这会创建回调逐层传递并降低可复用性。structEditItemSheet:View{Environment(\.dismiss)privatevardismissletitem:ItemStateprivatevarname:Stringinit(item:Item){self.itemitem _nameState(initialValue:item.name)}varbody:someView{NavigationStack{Form{TextField(Name,text:$name)}.navigationTitle(Edit Item).toolbar{ToolbarItem(placement:.cancellationAction){Button(Cancel){dismiss()}}ToolbarItem(placement:.confirmationAction){Button(Save){/* 保存并关闭 */}}}}}}基于枚举的 Sheet 管理当呈现多个不同的 sheet 时使用遵循Identifiable的枚举搭配.sheet(item:)而不是多个布尔状态属性structArticlesView:View{enumSheet:Identifiable{caseadd,edit(Article),categoriesvarid:String{switchself{case.add:addcase.edit(leta):edit-\(a.id)case.categories:categories}}}StateprivatevarpresentedSheet:Sheet?varbody:someView{List{/* ... */}.toolbar{Button(Add){presentedSheet.add}}.sheet(item:$presentedSheet){sheetinswitchsheet{case.add:AddArticleView()case.edit(letarticle):EditArticleView(article:article)case.categories:CategoriesView()}}}}原因单个State属性和一个.sheet(item:)修饰符取代 N 个布尔属性和 N 个 sheet 修饰符提高了可读性并防止同一时间只能有一个 sheet 的冲突。导航模式使用 NavigationStack 的类型安全导航structContentView:View{varbody:someView{NavigationStack{List{NavigationLink(Profile,value:Route.profile)NavigationLink(Settings,value:Route.settings)}.navigationDestination(for:Route.self){routeinswitchroute{case.profile:ProfileView()case.settings:SettingsView()}}}}}enumRoute:Hashable{caseprofilecasesettings}编程式导航structContentView:View{StateprivatevarnavigationPathNavigationPath()varbody:someView{NavigationStack(path:$navigationPath){List{Button(Go to Detail){navigationPath.append(DetailRoute.item(id:1))}}.navigationDestination(for:DetailRoute.self){routeinswitchroute{case.item(letid):ItemDetailView(id:id)}}}}}enumDetailRoute:Hashable{caseitem(id:Int)}使用 NavigationSplitView 的多列导航两列布局对侧边栏驱动的导航使用NavigationSplitView。在 iOS 16、macOS 13、tvOS 16、watchOS 9 上可用。structContentView:View{StateprivatevarselectedItem:Item.ID?varbody:someView{NavigationSplitView{List(items,selection:$selectedItem){iteminText(item.name)}.navigationTitle(Items)}detail:{ifletselectedItem,letitemitems.first(where:{$0.idselectedItem}){ItemDetailView(item:item)}else{ContentUnavailableView(Select an Item,systemImage:doc)}}}}三列布局structContentView:View{StateprivatevardepartmentId:Department.ID?StateprivatevaremployeeIdsSetEmployee.ID()varbody:someView{NavigationSplitView{List(model.departments,selection:$departmentId){deptinText(dept.name)}}content:{ifletdepartmentmodel.department(id:departmentId){List(department.employees,selection:$employeeIds){empinText(emp.name)}}else{Text(Select a department)}}detail:{EmployeeDetails(for:employeeIds)}}}配置列可见性NavigationSplitView(columnVisibility: $visibility)搭配NavigationSplitViewVisibility.detailOnly、.doubleColumn、.all列宽每列上使用.navigationSplitViewColumnWidth(min:ideal:max:)紧凑列NavigationSplitView(preferredCompactColumn: $column)控制窄设备上显示哪一列样式.navigationSplitViewStyle(.balanced)或.prominentDetail默认平台行为平台行为macOS列始终并排可见侧边栏有半透明材质可通过拖动调整列宽iPadOS常规侧边栏可以覆盖或推开详情支持通过工具栏按钮切换列可见性iOS / iPadOS紧凑折叠成单个NavigationStack侧边栏项显示展开箭头返回按钮在列之间导航iPhone所有尺寸始终折叠成堆栈侧边栏作为根列表出现选择将详情推入堆栈watchOS / tvOS折叠成单个堆栈Inspector可用性iOS 17.0、macOS 14.0用于补充信息的尾缘面板。在较宽的尺寸类别macOS、iPad 横屏下它显示为尾缘列。在紧凑尺寸类别iPhone下它自动适配为 sheet。基本 InspectorstructShapeEditor:View{StateprivatevarshowInspectorfalsevarbody:someView{MyEditorView().inspector(isPresented:$showInspector){InspectorContent()}.toolbar{ToolbarItem{Button{showInspector.toggle()}label:{Label(Inspector,systemImage:info.circle)}}}}}带列宽的 InspectorMyEditorView().inspector(isPresented:$showInspector){InspectorContent().inspectorColumnWidth(min:200,ideal:250,max:400)}带固定宽度的 InspectorMyEditorView().inspector(isPresented:$showInspector){InspectorContent().inspectorColumnWidth(300)}平台行为平台行为macOS尾缘侧边栏面板可通过拖动边缘调整大小与窗口工具栏集成iPadOS常规与内容并排的尾缘列可通过工具栏按钮切换iOS / iPadOS紧凑适配为 sheet 呈现支持滑动关闭iPhone所有尺寸总是以 sheet 形式呈现无尾缘列通过滑动或按钮关闭提示在应用的.commands中使用InspectorCommands以包含默认的 inspector 切换键盘快捷键。呈现修饰符全屏覆盖structContentView:View{StateprivatevarshowFullScreenfalsevarbody:someView{Button(Show Full Screen){showFullScreentrue}.fullScreenCover(isPresented:$showFullScreen){FullScreenView()}}}PopoverstructContentView:View{StateprivatevarshowPopoverfalsevarbody:someView{Button(Show Popover){showPopovertrue}.popover(isPresented:$showPopover){PopoverContentView().presentationCompactAdaptation(.popover)// 在 iPhone 上不适配为 sheet}}}关于alert和confirmationDialogAPI 模式请参阅latest-apis.md。汇总清单基于模型的 sheet 使用.sheet(item:)Sheet 在内部拥有自己的动作和关闭类型安全导航使用带navigationDestination(for:)的NavigationStack编程式导航使用NavigationPath侧边栏驱动的多列布局使用NavigationSplitView尾缘补充面板使用Inspector使用navigationSplitViewColumnWidth(min:ideal:max:)或inspectorColumnWidth(min:ideal:max:)设置列宽使用合适的呈现修饰符sheet、fullScreenCover、popoverAlert 和确认对话框使用带 actions 的现代 API避免向 sheet 传递 dismiss/save 回调呈现多个 sheet 时使用基于枚举的Identifiable类型搭配.sheet(item:)需要时可保存/恢复导航状态
RELATED

相关推荐

315页智慧城市方案Word排版:从样式体系到自动化改稿的完整指南

315页智慧城市方案Word排版:从样式体系到自动化改稿的完整指南

简介:这份智慧城市建设方案文档共315页,是面向政府信息化部门、智慧城市项目规划者与系统集成商的顶层设计参考。内容从项目概述、业务需求分析、功能与性能需求、建设难点及对策切入,逐步展开总体架构、技术架构、信息资源架构、开放平台与安…

📅 2026/10/12 3:42:36
写好架构决策记录(ADR)的完整指南:Context、Consequences 与不可变原则实战解析

写好架构决策记录(ADR)的完整指南:Context、Consequences 与不可变原则实战解析

【免费下载链接】architecture-decision-record Architecture decision record (ADR) examples for software planning, IT leadership, and template documentation 项目地址: https://gitcode.com/gh_mirrors/ar/architecture-decision-record 点击查看 免费下载 …

📅 2026/10/12 3:37:36
ant-design-blazor Progress 组件 StrokeLinecap 详解:圆角与方角边缘的切换与实现原理

ant-design-blazor Progress 组件 StrokeLinecap 详解:圆角与方角边缘的切换与实现原理

UI组件前端 【免费下载链接】ant-design-blazor 🌈A rich set of enterprise-class UI components based on Ant Design and Blazor. 项目地址: https://gitcode.com/gh_mirrors/an/ant-design-blazor 点击查看 免费下载 进度条末端的形状看似细节&…

📅 2026/10/12 3:37:36
MORE NEWS

更多资讯

📰

编译原理期末复习攻略:把握词法、语法与代码生成核心考点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

AI日报系统设计:信源过滤、语义分级与多端适配实践

1. 项目概述:这不是一份“新闻稿”,而是一套可复用的AI信息流处理系统“AI 日报(2026年10月5日)”这个标题乍看像一条社交媒体上的轻量资讯推送,但作为从业十多年、亲手搭建过二十多个垂直领域信息聚合系统的博主&…

📰

criterion.rs 的 bencher 兼容层(criterion_bencher_compat):把 bencher 基准测试平滑迁移到 Criterion.rs

开发工具性能测试 【免费下载链接】criterion.rs Statistics-driven benchmarking library for Rust 项目地址: https://gitcode.com/gh_mirrors/cr/criterion.rs 点击查看 免费下载 导读 本文聚焦 Criterion.rs 仓库中提供的 criterion_bencher_compat&#xff0…

📰

高频变压器设计:难点不在算,而在权衡

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

自动化老工程师90条实战经验:从入行到现场高手的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Docker 下搭建 Redis 集群:三主三从、故障转移与扩容实战

Docker 下搭建 Redis 集群,听起来就是拉镜像、起容器、敲一条 create 命令的事,但真正把三主三从跑起来,再经历过一次故障切换和扩容,才知道里面有不少细节是官方文档不会明确告诉你的。我会把一条完整的实操链路走完:…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬