ハイライト
iOS 18 の UIKit は SwiftUI Animation で UIView アニメーションを駆動可能。ジェスチャーシステムはフレームワーク間で依存関係を統一。Tab Bar は sidebar 形態に自動適応。
主要内容
UIKit で iPad app を書く開発者は皆同じ問題に直面——UITabBarController の tab bar と sidebar は独立した 2 つの UI。切り替え時に手動で state 管理が必要。コードが長くバグも出やすい。iPadOS 18 でついに統合——新しい UITab と UITabGroup API で app 構造を 1 回記述するだけで、システムが tab bar と sidebar の両形態を自動生成。ユーザーはドラッグで tab 順序もカスタマイズ可能。
trait 変更の処理も同様に面倒だった。以前は registerForTraitChanges で関心のある trait を手動登録し、コールバックで setNeedsLayout や setNeedsDisplay を呼ぶ必要があった。iOS 18 の automatic trait tracking では、layoutSubviews、drawRect などで trait を読むだけで UIKit が依存関係を自動記憶。trait 値が変わると対応する invalidation を自動トリガー。大量のボイラープレートを削除可能。
フレームワーク間協調の痛点も解消中。SwiftUI の Animation 型が UIKit view アニメーションを直接駆動可能(CustomAnimation 含む)。ジェスチャーシステムも統一——UIKit と SwiftUI のジェスチャー間で failure/requirement 関係を設定可能。新しい UIGestureRecognizerRepresentable プロトコルで UIKit ジェスチャーを SwiftUI 階層に埋め込み。
詳細
SwiftUI Animation で UIView を駆動
今回の更新で最も実用的な API 変更。UIView.animate(using:) は SwiftUI Animation 型を受け取り、インタラクティブアニメーションで特に有用——ジェスチャー中は .interactiveSpring、終了時は .spring。2 フェーズ間で速度がシームレスに継続(03:35):
switch gesture.state {
case .changed:
UIView.animate(.interactiveSpring) {
bead.center = gesture.translation
}
case .ended:
UIView.animate(.spring) {
bead.center = endOfBracelet
}
}
キーポイント:
.changed分支は.interactiveSpringで指に追従。適度なバウンス.ended分支は.springで終点固定。ジェスチャー終了瞬間から速度が自然に遷移- 2 フェーズは同じ velocity 伝達メカニズムを共有。初速度の手動計算不要
フレームワーク間ジェスチャー依存
SwiftUI view が UIKit view 内にネストされると、両フレームワークのジェスチャーが同時認識して競合する可能性。iOS 18 では name と delegate メソッドでフレームワーク間 failure requirement を設定可能(04:46):
// Inner SwiftUI double tap gesture
Circle()
.gesture(doubleTap, name: "SwiftUIDoubleTap")
// Outer UIKit single tap gesture
func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldRequireFailureOf other: UIGestureRecognizer
) -> Bool {
other.name == "SwiftUIDoubleTap"
}
キーポイント:
- SwiftUI ジェスチャーは
name:パラメータでタグ付け。UIKit 側はother.nameでマッチ - UIKit のシングルタップは SwiftUI ダブルタップが失敗してからトリガー。同時認識を回避
- 標準的な
UIGestureRecognizerDelegateメソッド。新プロトコル不要
Automatic trait tracking
layoutSubviews で trait を読むと UIKit が依存関係を自動追跡(06:40):
class MyView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
if traitCollection.horizontalSizeClass == .compact {
// apply compact layout
} else {
// apply regular layout
}
}
}
キーポイント:
layoutSubviews呼び出し時、UIKit はhorizontalSizeClassへのアクセスを記録- その trait が変化すると UIKit が自動で
setNeedsLayoutを呼ぶ - 以前は手動
registerForTraitChanges+ コールバック内setNeedsLayoutが必要——削除可能 - サポートメソッド:
layoutSubviews、drawRect:、traitCollectionDidChangeなど。完全リストはドキュメント参照
List environment trait
UICollectionView list section と UITableView 内の全 view が list environment trait を自動保有。UIListContentConfiguration と UIBackgroundConfiguration がこの trait に基づき外観を調整(07:43):
func configurations(for location: FileLocation) ->
(UIListContentConfiguration, UIBackgroundConfiguration) {
var contentConfiguration = UIListContentConfiguration.cell()
let backgroundConfiguration = UIBackgroundConfiguration.listCell()
contentConfiguration.text = location.title
contentConfiguration.image = location.thumbnailImage
return (contentConfiguration, backgroundConfiguration)
}
キーポイント:
UIListContentConfiguration.cell()は sidebar/通常スタイルを手動判別するロジックを置き換えUIBackgroundConfiguration.listCell()は list environment trait から外観を自動読み取り- 新しいコンストラクタ:
.listHeaderと.listFooter - list appearance をパラメータで渡す必要なし——cell に適用時に自動適応
UIUpdateLink
CADisplayLink を置き換える新 API。自動 view tracking と低遅延モード(11:18):
let updateLink = UIUpdateLink(
view: view,
actionTarget: self,
selector: #selector(update)
)
updateLink.requiresContinuousUpdates = true
updateLink.isEnabled = true
@objc func update(updateLink: UIUpdateLink,
updateInfo: UIUpdateInfo) {
view.center.y = sin(updateInfo.modelTime)
* 100 + view.bounds.midY
}
キーポイント:
- 構築時に view にバインド。可視 window に加入時に自動アクティブ、削除時に自動停止
updateInfo.modelTimeはディスプレイ同期時間。手動タイミングより正確requiresContinuousUpdates = trueで毎フレームトリガー。falseは他の更新(ジェスチャー、layer 変化)があるときのみ- 低遅延モードをサポート。描画系 app に適する
その他の更新
- Zoom transition:iOS 18 で zoom transition 追加。navigation と presentation をサポート。完全インタラクティブ——転場中にドラッグで中断可能(02:50)
- SF Symbols アニメーション:
.wiggle、.breathe、.rotateプリセット追加。.periodic(繰り返し回数と間隔指定)と.continuous動作。Magic Replace が badge と slash の遷移アニメーションを自動処理(12:47) - UICanvasFeedbackGenerator:大規模キャンバス app 向け新フィードバック生成器。作成時に view にバインド。フィードバックトリガー時に位置座標を渡す(15:02)
- Text formatting panel:UITextView にフォーマットパネル追加。フォント、サイズ、リスト、ハイライトなど。
textFormattingConfigurationでレイアウトカスタマイズ。nilで終了(16:14) - Text highlight:
textHighlightStyleとtextHighlightColorSchemeでテキストハイライト。5 種のプリセット配色(16:49) - Writing Tools:UITextView がデフォルトで Writing Tools UI を統合。編集可能 text view はインライン編集、非編集はオーバーレイパネル(17:40)
- Apple Pencil Pro:squeeze ジェスチャー、barrel-roll 角度、undo slider、PKToolPicker カスタムツール(19:01)
重要ポイント
-
やること:インタラクティブアニメーションで
UIViewPropertyAnimatorをUIView.animate(.spring)に置き換え。価値がある理由:SwiftUI spring の velocity 伝達がインタラクティブ/非インタラクティブフェーズ間でシームレス。コード量を半分以上削減。始め方:ジェスチャーの.changedと.ended分支でそれぞれUIView.animate(.interactiveSpring)とUIView.animate(.spring)を呼び、旧 animator コードを削除。 -
やること:
UITabBarItem配列をUITab/UITabGroup構造に移行。価値がある理由:新 API が tab bar と sidebar 形態に自動適応。Mac Catalyst と visionOS でもネイティブ体験。プラットフォームごとに二重のナビゲーションロジックを書く必要なし。始め方:UITabBarControllerのviewDidLoadでUITabとUITabGroupからtabs配列を構築。手動tabBar.items設定を削除。 -
やること:
registerForTraitChangesの手動 trait 登録コードを削除。価値がある理由:layoutSubviewsなどでの automatic trait tracking により手動登録は冗長。始め方:Xcode でregisterForTraitChangesをグローバル検索。各箇所で trait がlayoutSubviewsやdrawRect:で既にアクセスされているか確認。されていれば登録コードを削除。 -
やること:list スタイル手動判別を
UIListContentConfiguration.cell()とUIBackgroundConfiguration.listCell()に置き換え。価値がある理由:list environment trait が sidebar と insetGrouped 外観を自動適応。画面回転や split view 時に cell の手動 reconfigure 不要。始め方:cell 設定コードのisSidebar分支を探し、統一された.cell()/.listCell()コンストラクタに置き換え。
関連セッション
- Evolve your document launch experience — document-based app の起動画面をカスタマイズ。テンプレートドキュメント作成をサポート
- Elevate your tab and sidebar experience in iPadOS — UITab / UITabGroup の完全な使い方と sidebar カスタマイズ
- Enhance your UI animations and transitions — zoom transition と SwiftUI Animation 駆動 UIKit の詳細デモ
- What’s new in SF Symbols 6 — 新しい symbol アニメーションプリセットと Magic Replace 動作
- Squeeze the most out of Apple Pencil — Apple Pencil Pro の squeeze、barrel-roll、PKToolPicker カスタムツール
コメント
GitHub Issues · utterances