ハイライト
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 を置き換え。各 Tab に customizationID を付け、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 をワンタップ切り替え$customizationbinding がユーザーのカスタマイズ状態を保存し、次回起動時に自動復元
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 プロトコル実装全体を置き換え。EnvironmentValues、FocusValues、Transaction、ContainerValues に適用(13:52)。ForEach(subviewOf:) でサブビューを走査し、カスタムコンテナを構築(13:13)。
extension EnvironmentValues {
@Entry var karaokePartyColor: Color = .purple
}
テキスト選択 + 検索フォーカス + テキスト提案
TextField に selection 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 を走査し、各フラグメントを個別に描画- ぼかしたコピーをグロー下地として先に描画し、元のテキストを重ねてグロー効果を作成
重要ポイント
-
iPad app に sidebar/tab 切り替えを追加:
NavigationSplitViewで sidebar を模倣しているプロジェクトは、.sidebarAdaptableTabView に移行すればコードが減り、システムと一貫した挙動になり、ユーザーがタブをカスタマイズ可能。始め方:NavigationSplitViewをTabView + Tab + .sidebarAdaptableに置き換え、各 Tab にcustomizationIDを追加。 -
Control Widget で高頻度操作をロック画面/コントロールセンターへ:app を開かずにコア機能をトリガー(記録開始、状態切り替え、クイック撮影)。App Intents と連携すれば Shortcuts からも呼び出し可能。始め方:
ControlWidget実装を作成し、ControlWidgetButtonまたはControlWidgetToggleを定義、AppIntentをバインド。 -
onScrollVisibilityChangeで遅延ビデオ再生:リスト内のビデオがビューポートに入ると自動再生、出ると自動一時停止。省電力でスムーズな体験。始め方:VideoPlayerに.onScrollVisibilityChange(threshold: 0.2)コールバックを追加し play/pause を制御。 -
UIView.animate(animation:)で UIKit と SwiftUI アニメーションを統一:混在プロジェクトで UIKit 部分のプロパティアニメーションに SwiftUI スプリング曲線を使用。ジェスチャー駆動アニメーションは慣性速度を自動保持。timing curve の手動計算不要。始め方:UIView.animate(SwiftUI.Animation.spring(duration: 0.8))内で UIKit プロパティを変更。
関連セッション
- Improve your tab and sidebar experience on iPad — TabView 新構文と sidebarAdaptable 適応の詳細解説
- Enhance your UI animations and transitions — zoom トランジションと SwiftUI/UIKit アニメーション橋渡しの完全ガイド
- Demystify SwiftUI Containers — subviewOf、カスタムコンテナ、ContainerValues の原理と実践
- Dive deep into volumes and immersive spaces — volume ベースプレート、視点変化、没入レベル制御の詳細用法
- Create custom visual effects with SwiftUI — TextRenderer とカスタム視覚効果の開発チュートリアル
コメント
GitHub Issues · utterances