mcpField
A
axiom-swiftui-26-ref

axiom-swiftui-26-ref

github.com/charleswiltgen開発1.2k281 回インストール今日更新
リポジトリ

axiom-swiftui-26-ref について

Apple のバージョン 26 系プラットフォーム向け SwiftUI の新機能を解説するリファレンススキルです。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 デザインシステムからリッチテキスト編集まで、これらの機能強化により、すべての 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 以降

コメント