axiom-swiftui-26-ref について
Apple のバージョン 26 系プラットフォーム向け SwiftUI の新機能を解説するリファレンススキルです。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 デザインシステムからリッチテキスト編集まで、これらの機能強化により、すべての Apple プラットフォームで SwiftUI がさらに強力になります。
基本原則 低レベルのパフォーマンス改善からユーザーインターフェイスのボタンに至るまで、システム全体に大きな改善が加えられています。
このスキルを使う場面
- Liquid Glass デザインシステムの採用
- AttributedString を使ったリッチテキスト編集の実装
- WebView を使ったウェブコンテンツの埋め込み
- リストとスクロールのパフォーマンス最適化
- カスタムアニメーションでの @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) を使うと、項目(アバターなど)をグループの背景から除外できます。
ツールバーのモーフィング
NavigationStack 自体ではなく、NavigationStack 内の個々のビューに .toolbar {} を付けます。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") { } }
}
最大の注意点: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 を指定します。macOS のメニュー項目を追加するには ToolbarCommands() を追加します。
その他のツールバー機能
.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 を参照してください
カスタムビュー向けの Glass エフェクト
Button("To Top", systemImage: "chevron.up") { scrollToTop() }
.padding()
.glassEffect() // Add .interactive for custom controls on iOS
GlassEffectContainer— 複数の glass 要素が近接する場合に必須(glass は glass をサンプリングできません)glassEffectID(_:in:)— 名前空間を使用して glass 要素間を流動的にモーフィング遷移します- シートのモーフィング —
.matchedTransitionSource+.navigationTransition(.zoom(...))を使用して、ボタンからシートをモーフィングします
ボタンとコントロールの変更
- ボーダー付きボタンのデフォルトがカプセル形状に(
.buttonBorderShape(.roundedRectangle)でオーバーライド可能) .controlSize(.extraLarge)— 新しい特大ボタンサイズ- コンテナでの
.controlSize(.small)— iOS 26 以前の密度を維持します GlassButtonStyle(.clear/.glass/.tint)— Glass ボタンのバリアント(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 — Dynamic Type、トラッキング、国際化を含む完全なタイポグラフィシステム
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 は次のフレームに向けた準備をさらに進められるようになります。全体として、高いフレームレートで素早くスクロールしているときに、アプリでフレームがドロップする可能性が低くなります。
Lazy Stack を使った入れ子の ScrollView
写真カルーセルと複数軸のスクロール
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 Performance Instrument
Xcode の新しいプロファイリングツール
利用できるレーン:
- 長時間かかる View 本体の更新 — コストの高い本体の計算を特定します
- プラットフォーム View の更新 — UIKit/AppKit とのブリッジ処理のパフォーマンスを追跡します
- その他のパフォーマンス上の問題領域
参考資料 「インストゥルメントで SwiftUI のパフォーマンスを最適化する」(WWDC 2025)
関連項目 SwiftUI Performance — SwiftUI Instrument を使いこなす
Swift Concurrency との統合
コンパイル時のデータ競合安全性
@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 Concurrency — 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)
- 「visionOS で SwiftUI を使ってシーンを設定する」(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
段階的に SwiftUI を導入するため、NSHostingView を Interface Builder で直接使用できるようになりました。
RealityKit との統合
Observable エンティティ
@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 に、Web コンテンツを埋め込むための SwiftUI API が一式追加され、UIKit に切り替える必要がなくなりました。
WebView
Web コンテンツを表示する
import WebKit
struct ArticleView: View {
let articleURL: URL
var body: some View {
WebView(url: articleURL)
}
}
WebPage(監視可能なモデル)
Web コンテンツと豊富に連携する
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 で Web コンテンツを解析するには、JavaScriptCore を使用してください。代替手段については axiom-tvos を参照してください。
WebKit の高度な機能
- カスタムユーザーエージェント
- JavaScript の実行
- カスタム URL スキーム
- その他
参考資料「Meet WebKit for SwiftUI」(WWDC 2025)
AttributedString に対応した TextEditor
概要
SwiftUI に新たに追加されたリッチテキスト編集のサポートは、写真へのコメントなどの体験に最適です。TextView が AttributedString に対応しました!
注記:WWDC のトランスクリプトでは、編集上の表現として「TextView」が使われています。実際の SwiftUI API は TextEditor で、リッチテキスト編集用の AttributedString バインディングに対応しました。
プレーンテキストとリッチテキスト
- プレーンテキストの場合:
TextEditorよりもTextField("Label", text: $text, axis: .vertical)を優先してください。プレースホルダーテキスト、一貫したスタイル、自動的な垂直方向への拡張に対応しています(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 スキル)— Apple Intelligence の「モデルを使用」アクション向けの 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 による 3 次元プロットに対応しています。主なコンポーネントは、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 マクロ
🔧 Web コンテンツ用の 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 では遅延スタックを使用し、リストの自動パフォーマンス改善を活用します
- Liquid Glass:まず再コンパイルしてテストします。ツールバーのスペーサーを使用し、
.toolbar {}は NavigationStack ではなく個々のビューに付けます。シートからpresentationBackgroundを削除し、近接するグラス要素にはGlassEffectContainerを使用します - レイアウト:エッジツーエッジのレイアウトには
.padding()ではなく.safeAreaPadding()を使用します。詳しいガイドについてはaxiom-swiftui-layout-refを参照してください - リッチテキスト:
AttributedStringをTextEditorにバインドし、UX に合わせて属性を制限します - 空間表現(visionOS):奥行きには
Alignment3Dを使用し、.manipulable()は適切な場合にのみ使用します
トラブルシューティング
| 症状 | 解決方法 |
|---|---|
| iOS 26 SDK に更新した後も古いデザインが表示される | クリーンビルド(Shift-Cmd-K)を実行し、iOS 26 SDK を対象に再ビルドして、デプロイメントターゲットを確認します |
| iPhone で検索が上部に表示されたままになる | .searchable を List に直接ではなく、NavigationSplitView に配置します |
| @Animatable が「準拠していません」と表示される | すべてのプロパティを VectorArithmetic に準拠させるか、@AnimatableIgnored を付ける必要があります |
| TextEditor でリッチテキストの書式が失われる | String ではなく AttributedString をバインドします |
| ドラッグによる削除が機能しない | .dragConfiguration(allowDelete: true) を有効にし、さらに .onDragSessionUpdated を監視します |
| SliderTickContentForEach をコンパイルできない | カスタム構造体ではなく、数値を反復処理します(chapters.map(\.time))。Slider のセクションを参照してください |
| ナビゲーション中にツールバーがモーフィングしない | .toolbar {} を NavigationStack から、その内部の各ビューに移動します。Liquid Glass のセクションを参照してください |
リソース
WWDC:2025-256、2025-278(ウィジェットの新機能)、2025-287(SwiftUI 用 WebKit を紹介)、2025-310(インストゥルメントで SwiftUI のパフォーマンスを最適化する)、2025-323(新しいデザインで SwiftUI アプリを構築する)、2025-325(Swift Charts に第 3 の次元を追加する)、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 以降