关于 axiom-swiftui-26-ref
面向开发者的 SwiftUI 参考 Skill,介绍 Apple 26 系列平台版本的新功能,涉及 Liquid Glass、文本、控件、导航、空间布局与性能。
主要功能
- 01Liquid Glass 与工具栏 API
- 02富文本和行高控制
- 03滑块刻度、范围与标签
- 04搜索、URL 和安全区域更新
- 05列表与滚动性能建议
适用场景
- 01在应用界面采用 Liquid Glass
- 02构建带刻度和范围限制的滑块
- 03添加紧凑搜索和应用内 URL 打开
- 04优化大型列表与滚动布局
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ charleswiltgen/ axiom --skill axiom-swiftui-26-ref安装后在 Claude Code 中输入/axiom-swiftui-26-ref确认已加载。
详细介绍
SwiftUI 26 功能
概述
全面介绍 iOS 26、iPadOS 26、macOS Tahoe、watchOS 26 和 visionOS 26 中的 SwiftUI 新功能。从 Liquid Glass 设计系统到富文本编辑,这些增强功能让 SwiftUI 在所有 Apple 平台上都更加强大。
核心原则 从底层性能改进到用户界面中的按钮,整个系统都有重大改进。
何时使用此技能
- 采用 Liquid Glass 设计系统
- 使用 AttributedString 实现富文本编辑
- 使用 WebView 嵌入 Web 内容
- 优化列表和滚动性能
- 使用 @Animatable 宏创建自定义动画
- 在 visionOS 上构建 3D 空间布局
- 将 SwiftUI 场景桥接到 UIKit/AppKit 应用
- 实现多项拖放
- 使用 Chart3D 创建 3D 图表
- 在 visionOS 或 CarPlay 中添加小组件
- 为滑块添加自定义刻度标记(章节标记、数值指示器)
- 使用
enabledBounds限定滑块选择范围 - 自定义滑块外观(滑块按钮可见性、当前值标签)
- 创建带模糊效果的粘性安全区域栏
- 在应用内浏览器中打开 URL
- 使用系统样式的关闭和确认按钮
- 应用玻璃按钮样式(iOS 26.1+)
- 控制按钮尺寸行为
- 实现紧凑型搜索工具栏
- 调整文本行高或基线间距
系统要求
iOS 26+、iPadOS 26+、macOS Tahoe+、watchOS 26+、visionOS 26+
Liquid Glass 设计系统
如需全面了解,请参阅 axiom-liquid-glass(设计原则、变体、审核压力)和 axiom-liquid-glass-ref(全应用采用指南)。本节仅介绍 WWDC 256 专属 API。
自动采用
使用 iOS 26 SDK 重新编译后,导航容器、标签栏、工具栏、开关、分段选择器和滑块会自动采用新设计。带边框的按钮默认采用胶囊形状。工作表会使用 Liquid Glass 背景(移除任何 presentationBackground 自定义设置)。
工具栏 API(iOS 26)
ToolbarSpacer
.toolbar {
ToolbarItem(placement: .bottomBar) { Button("Archive", systemImage: "archivebox") { } }
ToolbarSpacer(.flexible, placement: .bottomBar) // Push items apart
ToolbarItem(placement: .bottomBar) { Button("Compose", systemImage: "square.and.pencil") { } }
}
// .fixed separates groups visually; .flexible pushes apart (like Spacer in HStack)
ToolbarItemGroup(视觉分组)
ToolbarItemGroup 中的项目共享一个玻璃背景“胶囊”。ToolbarItemPlacement 控制视觉外观:confirmationAction → glassProminent 样式,cancellationAction → 标准玻璃样式。使用 .sharedBackgroundVisibility(.hidden) 可将项目(例如头像)排除在分组背景之外。
工具栏变形
将 .toolbar {} 附加到 NavigationStack 内的各个视图(而不是 NavigationStack 本身)。iOS 26 会在推送/弹出过程中,在各视图的工具栏之间进行变形。对于需要保持稳定(不弹跳)的项目,可在不同屏幕上使用相同的 ToolbarItem(id:) 和 toolbar(id:):
// MailboxList
.toolbar(id: "main") {
ToolbarItem(id: "filter", placement: .bottomBar) { Button("Filter") { } }
ToolbarSpacer(.flexible, placement: .bottomBar)
ToolbarItem(id: "compose", placement: .bottomBar) { Button("New Message") { } }
}
// MessageList — "filter" absent (animates out), "compose" stays stable
.toolbar(id: "main") {
ToolbarSpacer(.flexible, placement: .bottomBar)
ToolbarItem(id: "compose", placement: .bottomBar) { Button("New Message") { } }
}
#1 易错点:在 NavigationStack 上设置工具栏 = 没有可供变形的对象。
DefaultToolbarItem
在工具栏布局中重新定位系统提供的项目(例如搜索):
DefaultToolbarItem(kind: .search, placement: .bottomBar)
// Replaces system's default placement of matching kind
在已折叠的 NavigationSplitView 侧边栏中使用它,可指定 iPhone 上哪一列显示搜索。为兼容旧版本,请使用 if #available(iOS 26.0, *) 包裹。
用户可自定义的工具栏
toolbar(id:) 支持用户自定义(重新排列、显示/隐藏)。在 iPadOS 上,只有 .secondaryAction 项目支持自定义。可选项目使用 showsByDefault: false。添加 ToolbarCommands() 可在 macOS 上添加菜单项。
其他工具栏功能
.navigationSubtitle("3 unread")— 标题下方的副标题- 工具栏项目上的
.badge(3)— 通知数量 - 单色图标渲染 — 减少视觉干扰;色调用于表达含义,而非装饰
- 滚动边缘模糊 — 自动应用,无需编写代码
底部对齐搜索
基础搜索 API:请参阅 axiom-swiftui-search-ref。本节仅介绍 iOS 26 的改进。
NavigationSplitView {
List { }.searchable(text: $searchText)
}
// Bottom-aligned on iPhone, top trailing on iPad (automatic)
// Use placement: .sidebar to restore sidebar-embedded search on iPad
searchToolbarBehavior(.minimize)— 紧凑型搜索栏,轻点后展开Tab(role: .search)— 专用搜索标签页;搜索栏会替代标签栏。请参阅 swiftui-nav-ref 第 5.7 节
自定义视图的玻璃效果
Button("To Top", systemImage: "chevron.up") { scrollToTop() }
.padding()
.glassEffect() // Add .interactive for custom controls on iOS
GlassEffectContainer— 附近有多个玻璃元素时必须使用(玻璃无法采样玻璃)glassEffectID(_:in:)— 使用命名空间实现玻璃元素之间的流体变形过渡- Sheet 变形 — 使用
.matchedTransitionSource+.navigationTransition(.zoom(...)),让 Sheet 从按钮处变形出现
按钮与控件变更
- 有边框按钮的默认形状为胶囊形(使用
.buttonBorderShape(.roundedRectangle)可覆盖) .controlSize(.extraLarge)— 新增超大按钮尺寸- 在容器上使用
.controlSize(.small)— 保留 iOS 26 之前的密度 GlassButtonStyle(.clear/.glass/.tint)— 玻璃按钮样式(iOS 26.1+).buttonSizing(.fit/.stretch/.flexible)— 控制按钮布局行为Button(role: .close)/Button(role: .confirm)— 使用系统样式的关闭/确认按钮.clipShape(.rect(cornerRadius: 12, style: .containerConcentric))— 圆角同心效果- 菜单:图标位于前缘,在 iOS/macOS 上保持一致
Slider 增强
iOS 26 新增自定义刻度标记、受限选择范围、当前值标签和滑块拇指可见性控制。
Slider 刻度
核心类型:SliderTick<V>、SliderTickContentForEach、SliderTickBuilder
// Static ticks with labels
Slider(value: $value, in: 0...10) {
Text("Rating")
} ticks: {
SliderTick(0) { Text("Min") }
SliderTick(5) { Text("Mid") }
SliderTick(10) { Text("Max") }
}
// Dynamic ticks from collection
SliderTickContentForEach(stops, id: \.self) { value in
SliderTick(value) { Text("\(Int(value))°").font(.caption2) }
}
// Step-based ticks (called for each step value)
Slider(value: $volume, in: 0...10, step: 2, label: { Text("Volume") }, tick: { value in
SliderTick(value) { Text("\(Int(value))") }
})
API 限制:SliderTickContentForEach 要求 Data.Element 与 SliderTick<V> 的值类型匹配。对于自定义结构体,请提取数值:chapters.map(\.time),然后通过 chapters.first(where: { $0.time == time }) 查找标签。
功能完整的 Slider
Slider(
value: $rating, in: 0...100,
neutralValue: 50, // Starting point / center value
enabledBounds: 20...80, // Restrict selectable range
label: { Text("Rating") },
currentValueLabel: { Text("\(Int(rating))") },
minimumValueLabel: { Text("0") },
maximumValueLabel: { Text("100") },
ticks: { SliderTick(50) { Text("Mid") } },
onEditingChanged: { editing in print(editing ? "Started" : "Ended") }
)
sliderThumbVisibility
.sliderThumbVisibility(.hidden) — 隐藏滑块拇指,适用于媒体进度指示器和极简 UI。选项:.automatic、.visible、.hidden。在 watchOS 上始终可见。
新视图修饰符
safeAreaBar
带集成渐进式模糊效果的固定栏:
List { ForEach(1...20, id: \.self) { Text("\($0). Item") } }
.safeAreaBar(edge: .bottom) {
Text("Bottom Action Bar").padding(.vertical, 15)
}
.scrollEdgeEffectStyle(.soft, for: .bottom) // or .hard
其工作方式类似于 safeAreaInset,但带有模糊效果。内容滚动时,栏会保持固定。
onOpenURL 增强
@Environment(\.openURL) var openURL
// openURL(url, prefersInApp: true) — Opens in SFSafariViewController-style in-app browser
// Default Link opens in Safari; prefersInApp keeps users in your app
searchToolbarBehavior
基础 .searchable API 请参阅 axiom-swiftui-search-ref。iOS 26 新增:
.searchable(text: $searchText)
.searchToolbarBehavior(.minimize) // Compact button, expands on tap
此外:.searchPresentationToolbarBehavior(.avoidHidingContent)(iOS 17.1+)可在搜索期间保持标题可见。
向后兼容的封装,适用于目标版本为 iOS 18+26 的应用:
extension View {
@ViewBuilder func minimizedSearch() -> some View {
if #available(iOS 26.0, *) {
self.searchToolbarBehavior(.minimize)
} else { self }
}
}
// Usage
.searchable(text: $searchText)
.minimizedSearch()
工具栏项的可用性模式:
.toolbar {
if #available(iOS 26.0, *) {
DefaultToolbarItem(kind: .search, placement: .bottomBar)
ToolbarSpacer(.flexible, placement: .bottomBar)
}
ToolbarItem(placement: .bottomBar) {
NewNoteButton()
}
}
.searchable(text: $searchText)
按钮角色、GlassButtonStyle、buttonSizing — 请参阅上方的 Liquid Glass 设计系统部分。
lineHeight(iOS 26)
设置文本行之间基线到基线的距离。相比 .lineSpacing(),它更直观;后者测量的是一行底部到下一行顶部的距离。
预设
Text("Lorem ipsum...")
.lineHeight(.loose) // Increased spacing for open layouts
.lineHeight(.tight) // Reduced spacing for compact layouts
.lineHeight(.normal) // Constant height based on point size multiple
.lineHeight(.variable) // Uses font metrics for height calculation
精确控制
// Scale proportionally to font size
Text("Scales with text size")
.lineHeight(.multiple(factor: 2))
// Relative to point size with fixed increase
Text("Point-size relative")
.lineHeight(.leading(increase: 30))
// Absolute fixed value — does NOT scale with Dynamic Type
Text("Fixed height")
.lineHeight(.exact(points: 30))
AttributedString 支持
var s = AttributedString("Paragraph\nwith multiple\nlines.")
s.lineHeight = .exact(points: 32)
s.lineHeight = .multiple(factor: 2.5)
s.lineHeight = .loose
与现有 API 对比
| API | 测量范围 | 可用版本 |
|---|---|---|
.lineHeight() | 基线到基线 | iOS 26+ |
.lineSpacing() | 一行底部到下一行顶部 | iOS 13+ |
.font(.body.leading(.tight)) | 字体级行距预设 | iOS 14+ |
交叉参考 axiom-typography-ref — 完整的排版系统,包括动态字体、字距和国际化
iPad 增强
菜单栏
通过向下轻扫菜单访问常用操作
.commands {
TextEditingCommands() // Same API as macOS menu bar
CommandGroup(after: .newItem) {
Button("Add Note") {
addNote()
}
.keyboardShortcut("n", modifiers: [.command, .shift])
}
}
// Creates menu bar on iPad when people swipe down
可调整大小的窗口
在 iPad 上流畅调整大小
// MIGRATION REQUIRED:
// Remove deprecated property list key in iPadOS 26:
// UIRequiresFullscreen (entire key deprecated, all values)
// For split view navigation, system automatically shows/hides columns
// based on available space during resize
NavigationSplitView {
Sidebar()
} detail: {
Detail()
}
// Adapts to resizing automatically
参考 “Elevate the design of your iPad app”(WWDC 2025)
macOS 窗口增强
同步窗口调整大小动画
.windowResizeAnchor(.topLeading) // Tailor where animation originates
// SwiftUI now synchronizes animation between content view size changes
// and window resizing - great for preserving continuity when switching tabs
性能改进
列表性能(侧重 macOS)
大型列表性能大幅提升
- 在 macOS 上,加载包含 100,000+ 项的列表快 6 倍
- 大型列表的更新速度快 16 倍
- 列表越大,性能提升越明显
- 所有平台(iOS、iPadOS、watchOS)均可受益
List(trips) { trip in // 100k+ items
TripRow(trip: trip)
}
// Loads 6x faster, updates 16x faster on macOS (iOS 26+)
滚动性能
减少丢帧
SwiftUI 改进了 iOS 和 macOS 上的用户界面更新调度。这提升了响应速度,也让 SwiftUI 能为即将到来的帧完成更多准备工作。总的来说,这降低了应用在高帧率下快速滚动时丢帧的几率。
嵌套 ScrollView 与 Lazy Stack
照片轮播与多轴滚动
ScrollView(.horizontal) {
LazyHStack {
ForEach(photoSets) { photoSet in
ScrollView(.vertical) {
LazyVStack {
ForEach(photoSet.photos) { photo in
PhotoView(photo: photo)
}
}
}
}
}
}
// Nested scrollviews now properly delay loading with lazy stacks
// Great for building photo carousels
SwiftUI 性能工具
Xcode 中的新性能分析工具
可用泳道:
- 视图主体更新耗时较长 — 找出开销较大的主体计算
- 平台视图更新 — 跟踪 UIKit/AppKit 桥接性能
- 其他性能问题区域
参考资料 “使用 Instruments 优化 SwiftUI 性能”(WWDC 2025)
交叉参考 SwiftUI 性能 — 掌握 SwiftUI Instrument
Swift 并发集成
编译时数据竞争安全性
@Observable
class TripStore {
var trips: [Trip] = []
func loadTrips() async {
trips = await TripService.fetchTrips()
// Swift 6 verifies data race safety at compile time
}
}
优势 在并发代码影响应用之前发现错误
参考资料
- “拥抱 Swift 并发”(WWDC 2025)
- “探索 SwiftUI 中的并发”(WWDC 2025)
交叉参考 Swift 并发 — Swift 6 严格并发模式
@Animatable 宏
概述
通过自动合成 animatableData 属性,简化自定义动画。
使用前(@Animatable 宏)
struct HikingRouteShape: Shape {
var startPoint: CGPoint
var endPoint: CGPoint
var elevation: Double
var drawingDirection: Bool // Don't want to animate this
// Tedious manual animatableData declaration
var animatableData: AnimatablePair<CGPoint.AnimatableData,
AnimatablePair<Double, CGPoint.AnimatableData>> {
get {
AnimatablePair(startPoint.animatableData,
AnimatablePair(elevation, endPoint.animatableData))
}
set {
startPoint.animatableData = newValue.first
elevation = newValue.second.first
endPoint.animatableData = newValue.second.second
}
}
}
使用后(@Animatable 宏)
@Animatable
struct HikingRouteShape: Shape {
var startPoint: CGPoint
var endPoint: CGPoint
var elevation: Double
@AnimatableIgnored
var drawingDirection: Bool // Excluded from animation
// animatableData automatically synthesized!
}
主要优势
- 删除手动编写的
animatableData属性 - 使用
@AnimatableIgnored排除属性 - SwiftUI 自动合成动画数据
交叉参考 SwiftUI Animation(swiftui-animation-ref 技能)— 全面的动画指南,涵盖 VectorArithmetic、Animatable 协议、@Animatable 宏、动画类型、Transaction 系统和性能优化
3D 空间布局(visionOS)
Alignment3D
基于深度的布局
struct SunPositionView: View {
@State private var timeOfDay: Double = 12.0
var body: some View {
HikingRouteView()
.overlay(alignment: sunAlignment) {
SunView()
.spatialOverlay(alignment: sunAlignment)
}
}
var sunAlignment: Alignment3D {
// Align sun in 3D space based on time of day
Alignment3D(
horizontal: .center,
vertical: .top,
depth: .back
)
}
}
Manipulable 修饰符
交互式 3D 对象
Model3D(named: "WaterBottle")
.manipulable() // People can pick up and move the object
表面吸附 API
@Environment(\.surfaceSnappingInfo) var snappingInfo: SurfaceSnappingInfo
var body: some View {
VStackLayout().depthAlignment(.center) {
Model3D(named: "waterBottle")
.manipulable()
Pedestal()
.opacity(snappingInfo.classification == .table ? 1.0 : 0.0)
}
}
参考资料
- “了解 SwiftUI 空间布局”(WWDC 2025)
- “使用 SwiftUI 在 visionOS 中设置场景”(WWDC 2025)
- “visionOS 新功能”(WWDC 2025)
场景桥接
概述
场景桥接让采用 UIKit 和 AppKit 生命周期的应用能够与 SwiftUI 场景互操作。应用可以用它打开仅支持 SwiftUI 的场景类型,也可以直接在 UIKit 或 AppKit 代码中使用 SwiftUI 独有的功能。
支持的场景类型
现在可以在 UIKit/AppKit 应用中使用
MenuBarExtra(macOS)ImmersiveSpace(visionOS)RemoteImmersiveSpace(macOS → Vision Pro)AssistiveAccess(iOS 26)
场景修饰符
支持与以下场景修饰符配合使用:
.windowStyle().immersiveEnvironmentBehavior()
RemoteImmersiveSpace
Mac 应用在 Vision Pro 上渲染立体内容
// In your macOS app
@main
struct MyMacApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
RemoteImmersiveSpace(id: "stereoView") {
// Render stereo content on Apple Vision Pro
// Uses CompositorServices
}
}
}
功能
- Mac 应用在 Vision Pro 上渲染立体内容
- 支持悬停效果和输入事件
- 使用 CompositorServices 和 Metal
参考资料 “沉浸式应用 Metal 渲染新功能”(WWDC 2025)
AssistiveAccess 场景
面向认知障碍用户的特殊模式
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
AssistiveAccessScene {
SimplifiedUI() // UI shown when iPhone is in AssistiveAccess mode
}
}
}
参考资料 “为 Assistive Access 自定义应用”(WWDC 2025)
AppKit 集成增强
AppKit 中的 SwiftUI 工作表
// Show SwiftUI view in AppKit sheet
let hostingController = NSHostingController(rootView: SwiftUISettingsView())
presentAsSheet(hostingController)
// Great for incremental SwiftUI adoption
NSGestureRecognizerRepresentable
// Bridge AppKit gestures to SwiftUI
struct AppKitPanGesture: NSGestureRecognizerRepresentable {
func makeNSGestureRecognizer(context: Context) -> NSPanGestureRecognizer {
NSPanGestureRecognizer()
}
func updateNSGestureRecognizer(_ recognizer: NSPanGestureRecognizer, context: Context) {
// Update configuration
}
}
Interface Builder 中的 NSHostingView
现在可以直接在 Interface Builder 中使用 NSHostingView,以逐步采用 SwiftUI。
RealityKit 集成
可观察实体
@Observable
class RealityEntity {
var position: SIMD3<Float>
var rotation: simd_quatf
}
struct MyView: View {
@State private var entity = RealityEntity()
var body: some View {
// SwiftUI views automatically observe changes
Text("Position: \(entity.position.x)")
}
}
PresentationComponent
直接从 RealityKit 实体呈现 SwiftUI 弹出框、警告和工作表。
// Present SwiftUI popovers from RealityKit entities
let popover = Entity()
mapEntity.addChild(popover)
popover.components[PresentationComponent.self] = PresentationComponent(
isPresented: $popoverPresented,
configuration: .popover(arrowEdge: .bottom),
content: DetailsView()
)
其他改进
ViewAttachmentComponent— 为实体添加 SwiftUI 视图GestureComponent— 让实体能够响应触摸和手势- 增强坐标转换 API
- 同步动画并绑定到组件
- 为 RealityView 提供新的尺寸行为
参考《Better Together: SwiftUI & RealityKit》(WWDC 2025)
WebView 与 WebPage
概述
WebKit 现已提供完整的 SwiftUI API,可用于嵌入网页内容,无需再切换到 UIKit。
WebView
显示网页内容
import WebKit
struct ArticleView: View {
let articleURL: URL
var body: some View {
WebView(url: articleURL)
}
}
WebPage(可观察模型)
与网页内容进行丰富交互
import WebKit
struct InAppBrowser: View {
@State private var page = WebPage()
var body: some View {
VStack {
Text(page.title ?? "Loading...")
WebView(page)
.ignoresSafeArea()
.onAppear {
page.load(URLRequest(url: articleURL))
}
HStack {
Button("Back") { page.goBack() }
.disabled(!page.canGoBack)
Button("Forward") { page.goForward() }
.disabled(!page.canGoForward)
}
}
}
}
WebPage 功能
- 以编程方式导航(
goBack()、goForward()) - 访问页面属性(
title、url、canGoBack、canGoForward) - 可观察 — SwiftUI 视图会自动更新
tvOS:WebView 和 WebPage 不支持 tvOS。tvOS 完全没有 WKWebView。若要在 tvOS 上解析网页内容,请使用 JavaScriptCore。请参阅 axiom-tvos 了解替代方案。
高级 WebKit 功能
- 自定义用户代理
- 执行 JavaScript
- 自定义 URL 方案
- 以及更多
参考《Meet WebKit for SwiftUI》(WWDC 2025)
使用 AttributedString 的 TextEditor
概述
SwiftUI 新增的富文本编辑支持非常适合评论照片等体验。TextView 现已支持 AttributedString!
注意 WWDC 演讲稿将“TextView”用作编辑性表述。实际的 SwiftUI API 是 TextEditor,现已支持绑定 AttributedString 以进行富文本编辑。
纯文本与富文本
- 纯文本:优先使用
TextField("Label", text: $text, axis: .vertical),而非TextEditor— 支持占位文本、样式一致,并可自动纵向扩展(iOS 16+) - 富文本:使用绑定
AttributedString的TextEditor(iOS 26+)—TextField不支持AttributedString
富文本编辑
struct CommentView: View {
@State private var comment = AttributedString("Enter your comment")
var body: some View {
TextEditor(text: $comment)
// Built-in text formatting controls included
// Users can apply bold, italic, underline, etc.
}
}
功能
- 内置文本格式控件(粗体、斜体、下划线、颜色等)
- 绑定到
AttributedString可保留格式 - 自动提供带格式选项的工具栏
高级 AttributedString 功能
自定义选项
- 段落样式
- 属性转换
- 限制用户可应用的属性
参考《Cook up a rich text experience in SwiftUI with AttributedString》(WWDC 2025)
交叉引用 App Intents 集成(app-intents-ref skill)— 用于 Apple Intelligence Use Model 操作的 AttributedString
拖放增强功能
拖动多个项目
根据选择拖动多个项目
struct PhotoGrid: View {
@State private var selectedPhotos: [Photo.ID] = []
var body: some View {
ScrollView {
LazyVGrid(columns: gridColumns) {
ForEach(model.photos) { photo in
view(photo: photo)
.draggable(containerItemID: photo.id)
}
}
}
.dragContainer(for: Photo.self, selection: selectedPhotos) { draggedIDs in
photos(ids: draggedIDs)
}
}
}
主要 API:
.draggable(containerItemID:containerNamespace:)将每个项目标记为拖动容器的一部分(命名空间默认为nil).dragContainer(for:selection:)在发生放置时按需提供类型化项目
DragConfiguration
自定义支持的操作
.dragConfiguration(DragConfiguration(allowMove: false, allowDelete: true))
观察拖动事件
.onDragSessionUpdated { session in
let ids = session.draggedItemIDs(for: Photo.ID.self)
if session.phase == .ended(.delete) {
trash(ids)
deletePhotos(ids)
}
}
拖动预览布局
.dragPreviewsFormation(.stack) // Items stack nicely on top of one another
// Other formations:
// - .default
// - .grid
// - .stack
在同一个滚动视图上组合所有修饰符(.dragContainer、.dragConfiguration、.dragPreviewsFormation、.onDragSessionUpdated),即可实现完整的多项目拖动体验。
3D 图表
概述
Swift Charts 现已通过 Chart3D 支持三维绘图。主要组件:Chart3D(容器)、SurfacePlot(连续曲面)、Chart3DPose(相机控制)、Chart3DSurfaceStyle(曲面外观)。
Chart3D 容器
import Charts
Chart3D {
SurfacePlot(x: "x", y: "y", z: "z") { x, y in
sin(x) * cos(y)
}
.foregroundStyle(Gradient(colors: [.orange, .pink]))
}
.chartXScale(domain: -3...3)
.chartYScale(domain: -3...3)
.chartZScale(domain: -3...3)
Chart3D 也接受数据集合:
Chart3D(dataPoints) { point in
// 3D mark for each data point
}
SurfacePlot
根据将 (x, y) 映射到 z 值的数学函数渲染连续曲面。
SurfacePlot(x: "X Axis", y: "Y Axis", z: "Z Axis") { x, y in
sin(sqrt(x * x + y * y))
}
曲面样式
SurfacePlot(x: "X", y: "Y", z: "Z") { x, y in sin(x) * cos(y) }
.foregroundStyle(.blue) // Solid color
.roughness(0.3) // 0 = smooth, 1 = rough
// Height-based coloring (color maps to z-value)
.foregroundStyle(Chart3DSurfaceStyle.heightBased(yRange: -1.0...1.0))
// Custom gradient mapped to height
.foregroundStyle(Chart3DSurfaceStyle.heightBased(
Gradient(colors: [.blue, .green, .yellow, .red]),
yRange: -1.0...1.0
))
可用的曲面样式:.heightBased(按 z 值着色)、.normalBased(按曲面法线方向着色)。
多个曲面
Chart3D {
SurfacePlot(x: "X", y: "Y", z: "Z") { x, y in sin(x) * cos(y) }
SurfacePlot(x: "X", y: "Y", z: "Z") { x, y in cos(x) * sin(y) + 2 }
}
Chart3DPose(相机控制)
控制视角。作为值传入可设置静态位置,也可绑定以进行交互式旋转。
@State private var chartPose: Chart3DPose = .default
Chart3D { /* ... */ }
.chart3DPose(chartPose) // Static — read-only
.chart3DPose($chartPose) // Binding — enables drag-to-rotate
预定义姿态:.default、.front、.back、.top、.bottom、.left、.right
使用特定角度自定义姿态:
Chart3DPose(azimuth: .degrees(45), inclination: .degrees(30))
在不同姿态之间添加动画:
Button("Top View") { withAnimation { chartPose = .top } }
Chart3DCameraProjection
控制 3D 深度向 2D 的投影方式。
Chart3D { /* ... */ }
.chart3DCameraProjection(.perspective) // Objects shrink with distance
.chart3DCameraProjection(.orthographic) // Objects maintain size regardless of depth
.chart3DCameraProjection(.automatic) // System decides
Z 轴修饰符
所有现有图表轴修饰符都有对应的 z 轴版本:
.chartZScale(domain:)— 设置 z 轴范围.chartZAxis()— 配置 z 轴标签和网格线
参考 “将 Swift Charts 带入第三维”(WWDC 2025)
小组件与控件
watchOS 和 macOS 上的控件
watchOS 26
struct FavoriteLocationControl: ControlWidget {
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(kind: "FavoriteLocation") {
ControlWidgetButton(action: MarkFavoriteIntent()) {
Label("Mark Favorite", systemImage: "star")
}
}
}
}
// Access from watch face or Shortcuts
macOS
控件现在也会显示在 Mac 的控制中心中。
visionOS 上的小组件
自定义细节级别
struct CountdownWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "Countdown") { entry in
CountdownView(entry: entry)
}
}
}
struct PhotoCountdownView: View {
@Environment(\.levelOfDetail) var levelOfDetail: LevelOfDetail
var body: some View {
switch levelOfDetail {
case .default:
RecentPhotosView() // Full detail when close
case .simplified:
CountdownView() // Simplified when further away
default:
CountdownView()
}
}
}
CarPlay 上的小组件
CarPlay 上的实时活动
实时活动现在会显示在 CarPlay 屏幕上,方便驾驶时快速查看信息。
其他小组件功能
- 基于推送的更新 API
- watchOS 的新相关性 API
参考 “小组件新功能”(WWDC 2025)
迁移清单
已弃用的 API
❌ 在 iPadOS 26 中移除
<key>UIRequiresFullscreen</key>
应用必须支持 iPad 上的可调整大小窗口。
自动采用(仅需重新编译)
✅ 导航栏、标签栏和工具栏采用 Liquid Glass 设计
✅ iPhone 上的搜索栏移至底部对齐
✅ 列表性能提升(加载速度提高 6 倍,更新速度提高 16 倍)
✅ 滚动性能提升
✅ 系统控件(开关、选择器、滑块)采用新外观
✅ 带边框的按钮默认采用胶囊形状
✅ 控件高度更新(macOS 上略高)
✅ 工具栏中的图标以单色渲染
✅ 菜单:图标位于前导边缘,且在 iOS 和 macOS 上保持一致
✅ 工作表会自动从对话框变形展开
✅ 系统工具栏下方的滚动边缘模糊/淡出效果
审查项目(移除旧的自定义设置)
⚠️ 从工作表中移除 presentationBackground(让 Liquid Glass 材质自然呈现)
⚠️ 移除工具栏区域后方的额外背景/变暗效果
⚠️ 移除硬编码的控件高度(使用自动尺寸调整)
⚠️ 将分区标题更新为标题式大小写(不再自动转为全大写)
手动适配(代码更改)
🔧 工具栏间隔项(.fixed)
🔧 工具栏中带色调的醒目按钮
🔧 自定义视图的玻璃效果(.glassEffect())
🔧 用于玻璃元素之间形变过渡的 glassEffectID
🔧 用于多个相邻玻璃元素的 GlassEffectContainer
🔧 使用 sharedBackgroundVisibility(.hidden) 将工具栏项目从分组背景中移除
🔧 按钮弹出工作表时的形变过渡(navigationZoomTransition)
🔧 搜索标签页角色(Tab(role: .search))
🔧 紧凑搜索工具栏(.searchToolbarBehavior(.minimize))
🔧 超大按钮(.controlSize(.extraLarge))
🔧 同心矩形形状(.containerConcentric)
🔧 iPad 菜单栏(.commands)
🔧 窗口调整大小锚点(.windowResizeAnchor())
🔧 用于自定义形状/修饰符的 @Animatable 宏
🔧 用于网页内容的 WebView
🔧 绑定 AttributedString 的 TextEditor
🔧 使用 .dragContainer 增强拖放功能
🔧 滑块刻度(SliderTick、SliderTickContentForEach)
🔧 滑块滑块可见性(.sliderThumbVisibility())
🔧 带模糊效果的安全区域栏(.safeAreaBar() + .scrollEdgeEffectStyle())
🔧 在应用内打开 URL(openURL(url, prefersInApp: true))
🔧 关闭和确认按钮角色(Button(role: .close))
🔧 玻璃按钮样式(GlassButtonStyle — iOS 26.1+)
🔧 按钮尺寸控制(.buttonSizing())
🔧 工具栏形变过渡(NavigationStack 中每个视图各自使用 .toolbar {})
🔧 用于工具栏中系统组件的 DefaultToolbarItem
🔧 稳定的工具栏项目(使用跨屏幕匹配 ID 的 toolbar(id:))
🔧 用户可自定义的工具栏(使用 CustomizableToolbarContent 的 toolbar(id:))
🔧 行高控制(.lineHeight() — 基线到基线的距离)
🔧 标签栏最小化(.tabBarMinimizeBehavior(.onScrollDown))
🔧 标签视图底部配件(.tabViewBottomAccessory(isEnabled:content:) — iOS 26.1+)
最佳实践
- 性能:使用新版 SwiftUI Instrument 进行性能分析;在嵌套的 ScrollView 中使用惰性堆栈;信任列表性能的自动改进
- 液态玻璃:先重新编译并测试;使用工具栏间隔项;将
.toolbar {}附加到单个视图上(而非 NavigationStack);从工作表中移除presentationBackground;使用GlassEffectContainer容纳相邻的玻璃元素 - 布局:使用
.safeAreaPadding()实现边缘到边缘布局(而非.padding())。完整指南参见axiom-swiftui-layout-ref - 富文本:将
AttributedString绑定到TextEditor;根据用户体验需求限制属性 - 空间计算(visionOS):使用
Alignment3D表示深度;仅在合适的场景使用.manipulable()
故障排除
| 症状 | 修复方法 |
|---|---|
| 更新到 iOS 26 SDK 后仍显示旧设计 | 清理构建(Shift-Cmd-K),以 iOS 26 SDK 为目标重新构建,并检查部署目标 |
| iPhone 上的搜索栏仍停留在顶部 | 将 .searchable 放在 NavigationSplitView 上,而不是直接放在 List 上 |
| @Animatable 提示“does not conform” | 所有属性都必须是 VectorArithmetic,或标记为 @AnimatableIgnored |
| TextEditor 中的富文本格式丢失 | 绑定 AttributedString,而不是 String |
| 拖动删除不起作用 | 启用 .dragConfiguration(allowDelete: true),并观察 .onDragSessionUpdated |
| SliderTickContentForEach 无法编译 | 遍历数值(chapters.map(\.time)),而不是自定义结构体 — 参见“滑块”部分 |
| 导航过程中工具栏没有形变过渡 | 将 .toolbar {} 从 NavigationStack 移到其中的每个视图上 — 参见“液态玻璃”部分 |
资源
WWDC:2025-256、2025-278(Widgets 新功能)、2025-287(认识 SwiftUI 的 WebKit)、2025-310(使用 Instruments 优化 SwiftUI 性能)、2025-323(使用全新设计构建 SwiftUI 应用)、2025-325(将 Swift Charts 带入第三维度)、2025-341(使用 AttributedString 在 SwiftUI 中打造丰富的文本体验)
文档:/swiftui、/swiftui/defaulttoolbaritem、/swiftui/toolbarspacer、/swiftui/searchtoolbarbehavior、/swiftui/view/toolbar(id:content:)、/swiftui/view/tabbarminimizebehavior(_:)、/swiftui/view/tabviewbottomaccessory(isenabled:content:)、/swiftui/slider、/swiftui/slidertick、/swiftui/slidertickcontentforeach、/webkit、/foundation/attributedstring、/charts、/charts/chart3d、/charts/surfaceplot、/charts/chart3dpose、/charts/chart3dcameraprojection、/charts/chart3dsurfacestyle、/realitykit/presentationcomponent
技能:axiom-swiftui-performance、axiom-liquid-glass、axiom-swift-concurrency、axiom-app-intents-ref、axiom-swiftui-search-ref
主要来源 WWDC 2025-256「SwiftUI 新功能」。其他内容来自 2025-323(使用全新设计构建 SwiftUI 应用)、2025-287(认识 SwiftUI 的 WebKit)以及 Apple 文档。 版本 iOS 26+、iPadOS 26+、macOS Tahoe+、watchOS 26+、visionOS 26+