WWDC Quick Look 💓 By SwiftGGTeam
What’s new in SwiftUI

What’s new in SwiftUI

元の動画を見る

ハイライト

TabView に type-safe 構文と .sidebarAdaptable スタイルが追加。1 つのコードベースで tab bar と sidebar を切り替え、ユーザーがタブの並べ替えと非表示を自由に行えます。


主要内容

iPad の sidebar app には長年、厄介な問題がありました。コンテンツが多いとき sidebar は便利ですが、画面スペースが限られると tab bar の方がコンパクト。以前は NavigationSplitView でこの切り替えを模倣する必要があり、コードが複雑で挙動も一貫しませんでした。iOS 18 では TabView.sidebarAdaptable スタイルが追加。1 つの modifier で tab bar と sidebar を自由に切り替え、タブの並べ替えと非表示のカスタマイズもシステム標準で提供されます。

今回の SwiftUI 更新は 4 つの領域をカバー。第 1 に app の刷新:TabView の新構文、Mesh Gradient、Swift Charts の関数プロット、動的 Table 列、Control Widgets。第 2 にプラットフォーム適応:macOS ウィンドウスタイルのカスタマイズ(plain style、floating level、デフォルト位置)、visionOS の pushWindow とカスタム hover effect、Apple Pencil Pro の squeeze ジェスチャー。第 3 にフレームワーク基盤:カスタムコンテナ(subviewOf)、@Entry マクロ、テキスト選択 API、onScrollGeometryChange、Swift 6 互換性、UIKit/AppKit アニメーション橋渡し。第 4 に没入体験:volume baseplate の表示制御、没入空間の許可レベル、passthrough ビデオエフェクト、カスタム TextRenderer。


詳細

TabView 新構文

TabView に type-safe な Tab イニシャライザが追加され、従来の文字列ベース tabItem を置き換え。各 TabcustomizationID を付け、TabViewCustomization 状態と組み合わせてユーザーの並べ替え・非表示設定を永続化(01:38)。

TabView {
    Tab("Parties", image: "party.popper") {
        PartiesView(parties: Party.all)
    }
    .customizationID("karaoke.tab.parties")

    Tab("Planning", image: "pencil.and.list.clipboard") {
        PlanningView()
    }
    .customizationID("karaoke.tab.planning")
}
.tabViewStyle(.sidebarAdaptable)
.tabViewCustomization($customization)

キーポイント:

  • Tab("Parties", image:...).tabItem { Label(...) } を置き換え、コンパイル時にタブ設定エラーを検出
  • .sidebarAdaptable で tab bar と sidebar をワンタップ切り替え
  • $customization binding がユーザーのカスタマイズ状態を保存し、次回起動時に自動復元

Sheet 統一サイズ + Zoom トランジション

Sheet のサイズにクロスプラットフォーム統一方案が登場。.presentationSizing(.form) でコンパクトなフォーム、.page で全ページ(02:28)。ナビゲーショントランジションに .zoom エフェクトが追加。matchedTransitionSource@Namespace で要素のスケールトランジション(02:39)。

Control Widgets

新しい ControlWidget プロトコルで、数行のコードでコントロールセンターやロック画面にボタンやトグルを作成。Action Button にもバインド可能(03:18)。

struct StartPartyControl: ControlWidget {
    var body: some ControlWidgetConfiguration {
        StaticControlConfiguration(kind: "com.apple.karaoke_start_party") {
            ControlWidgetButton(action: StartPartyIntent()) {
                Label("Start the Party!", systemImage: "music.mic")
                Text(PartyManager.shared.nextParty.name)
            }
        }
    }
}

キーポイント:

  • ControlWidgetButton の action は AppIntent を受け取り、Shortcuts/App Intents と連携
  • コントロールは動的コンテンツ(次のパーティ名など)を表示可能

Swift Charts 関数プロット + 動的 Table 列

LinePlot で数学関数を直接プロット(03:49)。TableColumnForEach で列を動的生成(04:18)。

Mesh Gradient

グリッド点間で色を補間し、豊かなグラデーション効果を作成(04:42)。

MeshGradient(
    width: 3,
    height: 3,
    points: [
        .init(0, 0), .init(0.5, 0), .init(1, 0),
        .init(0, 0.5), .init(0.3, 0.5), .init(1, 0.5),
        .init(0, 1), .init(0.5, 1), .init(1, 1)
    ],
    colors: [
        .red, .purple, .indigo,
        .orange, .cyan, .blue,
        .yellow, .green, .mint
    ]
)

キーポイント:

  • points 配列がグリッド座標(0〜1 範囲)を定義。オフセットで非対称グラデーションを作成
  • colors 配列は points と 1 対 1 対応。システムが自動補間

macOS ウィンドウカスタマイズ

Window scene は .windowStyle(.plain) でデフォルト装飾を除去、.windowLevel(.floating) で最前面表示、defaultWindowPlacement で初期位置を制御(07:04)。WindowDragGesture でタイトルバーなしウィンドウもドラッグ可能(07:30)。

visionOS:pushWindow + Hover Effect

pushWindow 環境アクションでウィンドウを開きながらソースウィンドウを非表示— 集中型ワークフローに最適(08:18)。新しいクロージャベース hoverEffect で hover 状態のスケールなど視覚フィードバックを精密制御(08:47)。

@Entry マクロ + カスタムコンテナ

@Entry マクロが 1 行で EnvironmentKey プロトコル実装全体を置き換え。EnvironmentValuesFocusValuesTransactionContainerValues に適用(13:52)。ForEach(subviewOf:) でサブビューを走査し、カスタムコンテナを構築(13:13)。

extension EnvironmentValues {
    @Entry var karaokePartyColor: Color = .purple
}

テキスト選択 + 検索フォーカス + テキスト提案

TextFieldselection binding が追加。選択範囲の読み書きが可能(15:06)。.searchFocused binding で検索フィールドのフォーカスを制御(15:29)。.textInputSuggestions で任意のテキストフィールドにオートコンプリート(15:41)。

ScrollView の新 API

onScrollGeometryChange でスクロールオフセット変化に効率的に応答(16:23)。onScrollVisibilityChange でスクロールによる画面内外への出入りを検出(16:42)。ScrollPosition.scrollTo(edge:) でプログラム的に端へスクロール(16:54)。

UIKit/AppKit アニメーション橋渡し

UIView.animate(animation:)NSAnimationContext.animate(animation:) で UIKit/AppKit のプロパティ変更に SwiftUI スプリングアニメーションを使用。ジェスチャー駆動アニメーションは速度を自動保持(18:34)。

visionOS 没入空間制御

volume は .volumeBaseplateVisibility でベースプレート表示を制御(19:59)。.onVolumeViewpointChange で視点角度の変化に応答(20:15)。没入空間の ImmersionStyle.progressive で最小・初期没入比率を設定可能に(20:38)。.preferredSurroundingsEffect(.colorMultiply(.purple)) で passthrough ビデオに色フィルターを重ねる(21:00)。

カスタム TextRenderer

TextRenderer プロトコルで Text ビューにカスタム描画を重ねられます。ぼかしグロー効果など(21:33)。

struct KaraokeRenderer: TextRenderer {
    func draw(layout: Text.Layout, in context: inout GraphicsContext) {
        for line in layout {
            for run in line {
                var glow = context
                glow.addFilter(.blur(radius: 8))
                glow.addFilter(purpleColorFilter)
                glow.draw(run)
                context.draw(run)
            }
        }
    }
}

Text("A Whole View World")
    .textRenderer(KaraokeRenderer())

キーポイント:

  • Text.Layout の line と run を走査し、各フラグメントを個別に描画
  • ぼかしたコピーをグロー下地として先に描画し、元のテキストを重ねてグロー効果を作成

重要ポイント

  1. iPad app に sidebar/tab 切り替えを追加NavigationSplitView で sidebar を模倣しているプロジェクトは、.sidebarAdaptable TabView に移行すればコードが減り、システムと一貫した挙動になり、ユーザーがタブをカスタマイズ可能。始め方:NavigationSplitViewTabView + Tab + .sidebarAdaptable に置き換え、各 Tab に customizationID を追加。

  2. Control Widget で高頻度操作をロック画面/コントロールセンターへ:app を開かずにコア機能をトリガー(記録開始、状態切り替え、クイック撮影)。App Intents と連携すれば Shortcuts からも呼び出し可能。始め方:ControlWidget 実装を作成し、ControlWidgetButton または ControlWidgetToggle を定義、AppIntent をバインド。

  3. onScrollVisibilityChange で遅延ビデオ再生:リスト内のビデオがビューポートに入ると自動再生、出ると自動一時停止。省電力でスムーズな体験。始め方:VideoPlayer.onScrollVisibilityChange(threshold: 0.2) コールバックを追加し play/pause を制御。

  4. UIView.animate(animation:) で UIKit と SwiftUI アニメーションを統一:混在プロジェクトで UIKit 部分のプロパティアニメーションに SwiftUI スプリング曲線を使用。ジェスチャー駆動アニメーションは慣性速度を自動保持。timing curve の手動計算不要。始め方:UIView.animate(SwiftUI.Animation.spring(duration: 0.8)) 内で UIKit プロパティを変更。


関連セッション

コメント

GitHub Issues · utterances