mcpField
A
axiom-swiftui-26-ref

axiom-swiftui-26-ref

github.com/charleswiltgen开发1.2k281 次安装今天更新
代码仓库

关于 axiom-swiftui-26-ref

面向开发者的 SwiftUI 参考 Skill,介绍 Apple 26 系列平台版本的新功能,涉及 Liquid Glass、文本、控件、导航、空间布局与性能。

主要功能

  1. 01Liquid Glass 与工具栏 API
  2. 02富文本和行高控制
  3. 03滑块刻度、范围与标签
  4. 04搜索、URL 和安全区域更新
  5. 05列表与滚动性能建议

适用场景

  1. 01在应用界面采用 Liquid Glass
  2. 02构建带刻度和范围限制的滑块
  3. 03添加紧凑搜索和应用内 URL 打开
  4. 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+

评论

支持 Markdown