ハイライト
Photos picker は iOS 16 でスクリーンショット、画面録画、スローモーション、シネマティック動画などのフィルターを拡張し、
all/notの複合フィルターを追加。AppKit、SwiftUI、NSOpenPanel、watchOS 経由で同じプライバシー保護の選択フローをより多くのプラットフォームへ広げました。
主要内容
多くの App はユーザーに数枚の写真を選んでもらえれば十分です。
独自の写真選択 UI を実装すると、App は写真ライブラリ権限の要求、権限状態の処理、アルバム UI の維持、ライブラリ全体へのアクセス理由の説明が必要になりがちです。Photos picker の考え方はより直接的です。選択 UI はシステムが提供し、App プロセス外で動作します。ユーザーがアセットを選ぶと、App は結果だけを受け取り、写真ライブラリアクセス権限は不要です。(00:18)
WWDC 2022 の更新は主に 3 つの問題を解きます。
第一に、フィルター条件の細分化です。以前は画像、動画、Live Photo を絞れましたが、今はスクリーンショット、画面録画、スローモーション動画も絞れ、PHAsset.PlaybackStyle でフィルターを作れます。all と not により「すべての画像だがスクリーンショットは除外」など、実プロダクトに近いロジックが書けます。(00:59)
第二に、選択器が半分の高さの sheet 以外のワークフローにも入れます。iOS 16 では asset identifier で選択解除でき、moveAsset で選択順を調整できます。カスタム UI で選択済み写真を管理する場面向けです。(02:32)
第三に、Photos picker は iOS / iPadOS 専用 API ではなくなりました。macOS と watchOS に広がり、AppKit と SwiftUI インターフェースが提供されます。SwiftUI の PhotosPicker は iOS、iPadOS、macOS、watchOS で使え、プラットフォームと利用可能スペースに応じたレイアウトを選びます。(03:24、07:43)
詳細
より精密な PHPickerFilter で選択可能コンテンツを制御
(02:04)フィルターはこの Session で最も実用的な更新です。Justin の例は単純で、スクリーンショット拼接 App はスクリーンショットだけを表示し、動画編集 App は特定の動画タイプだけを表示したいかもしれません。無関係なアセットを選択器の外に置けば、ユーザーのタップが減り、App も無効入力を減らせます。
var configuration = PHPickerConfiguration()
// iOS 15
// Shows videos and Live Photos
configuration.filter = .any(of: [.videos, .livePhotos])
// New: iOS 15
// Shows screenshots only
configuration.filter = .screenshots
// New: iOS 15
// Shows images excluding screenshots
configuration.filter = .all(of: [.images, .not(.screenshots)])
// New: iOS 16
// Shows cinematic videos
configuration.filter = .cinematicVideos
キーポイント:
PHPickerConfiguration()で選択器設定を作成し、フィルター、選択順、上限はすべてここに紐づきます。.any(of: [.videos, .livePhotos])はいずれかのタイプに一致すれば表示。「動画または Live Photo」の和集合向けです。.screenshotsは新しいアセットタイプフィルターで、スクリーンショット拼接、バグ報告、チュートリアル注釈 App に直接使えます。.all(of: [.images, .not(.screenshots)])はallとnotを組み合わせ「画像かつスクリーンショット除外」を表現します。.cinematicVideosは iOS 16 のシネマティック動画向け。Session では Cinematic videos、depth effect photos、bursts を除く新フィルターは iOS 16 SDK ビルドで iOS 15 へ戻せると説明されています。(01:38)
UIKit で PHPickerConfiguration を継続利用
(00:18)UIKit で既に PHPickerViewController を使っているプロジェクトなら、2022 年の変更で入口全体を替える必要はありません。設定を作り、フィルター、選択順、上限を設定して picker を作成します。
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selection = .ordered
configuration.selectionLimit = 10
let picker = PHPickerViewController(configuration: configuration)
キーポイント:
configuration.filter = .imagesで画像のみ表示します。configuration.selection = .orderedはユーザー選択順を保持し、アルバム、コラージュ、ストーリーボード向けです。configuration.selectionLimit = 10は最大 10 件に制限し、過多なアセット処理を避けます。PHPickerViewController(configuration:)はシステム選択器を作成し、独立プロセスで動作するため写真ライブラリ権限は不要です。(00:24)
AppKit 版で macOS も同じ設定を利用
(07:00)macOS の Photos picker は複数選択、グリッドズーム、検索をサポートします。AppKit API は UIKit に近く、依然 PHPickerConfiguration を使います。違いは AppKit では PHPickerViewController が NSViewController サブクラスであることです。
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selectionLimit = 10
let picker = PHPickerViewController(configuration: configuration)
キーポイント:
- AppKit 版は
PHPickerConfigurationを再利用し、UIKit と AppKit で設定の大半を共有できます。 configuration.filter = .imagesは macOS でも画像のみに制限します。configuration.selectionLimit = 10は複数選択の上限を制御します。- Session はメディア系 Mac App に新 Photos picker をデフォルトにしつつ、ファイルシステム資産用に
NSOpenPanelを残すことを推奨します。(05:23)
NSOpenPanel が自動的に写真ライブラリ入口を得る
(04:30)Mac App がたまに数枚の画像や動画を選ぶだけなら、NSOpenPanel で十分な場合があります。2022 年から NSOpenPanel にも新しい写真選択 UI が現れ、iCloud Photos のアセットも追加適応なしで選べます。
ライフサイクルの注意:写真ライブラリから選んだファイルはいつでもシステムに削除される可能性があります。長期保持が必要なら App 管理の場所へコピーしてください。(05:00)
SwiftUI PhotosPicker が Binding で選択結果を受け取る
(07:43)SwiftUI に PhotosPicker ビューが追加されました。選択結果を binding に書き込み、ラベルは呼び出し側が提供します。同じコードが iOS、iPadOS、macOS、watchOS で使え、システムが適切なレイアウトを選びます。
struct ContentView: View {
@Binding selection: [PhotosPickerItem]
var body: some View {
PhotosPicker(
selection: $selection,
matching: .images
) {
Text("Select Photos")
}
}
}
キーポイント:
@Binding selection: [PhotosPickerItem]は選択結果を保持します。まだ実データを含まないプレースホルダー集合です。PhotosPicker(selection:matching:)で SwiftUI 選択器を作成します。selection: $selectionはユーザー選択を外部状態に書き戻し、view model での反応に適しています。matching: .imagesはフィルター意味を再利用し画像のみ表示します。Text("Select Photos")は選択器のトリガーラベルで、ボタンやアイコンに置き換え可能です。
選択結果はオンデマンドで読み込む
(08:29)PhotosPickerItem はプレースホルダーです。実データはユーザー選択後に読み込みます。iCloud Photos からのダウンロードが必要だがネットワークがないなど、失敗もあり得ます。大きな動画はダウンロードに時間がかかるため、Session は画面全体を覆うブロッキングインジケータではなく、各項目のインライン loading UI を推奨します。
PhotosPicker は Transferable でデータを読み込みます。単純な場合は SwiftUI Image を直接読み込めます。データ型を制御したい場合は独自モデルを Transferable に準拠させます。多数項目や大きな動画は FileTransferRepresentation でファイルとして読み込み、すべてをメモリに載せないようにします。(09:21、09:54)
ファイル形式読み込みでは、受け取ったファイルを App ディレクトリへコピーし、不要になったら削除する責任もあります。(10:11)
watchOS は短いフローの画像選択に適する
(05:50)watchOS にも Photos picker があり、同様に独立プロセスで動作し、写真ライブラリ権限は不要です。グリッドと collection 閲覧、選択順と上限の設定をサポートします。
制限も明確です。watchOS picker は画像のみ表示します。一般に端末に 500 枚超があると直近 500 枚だけ表示します。Family Setup では iCloud Photos から直近 1000 枚を選べ、ネットワークダウンロードが必要な場合は閉じる前に loading UI を表示します。(06:29、13:17)
重要ポイント
1. スクリーンショット拼接の入口
- やること:スクリーンショット拼接 App のインポートボタンに Photos picker を接続し、スクリーンショットのみ表示する。
- 価値がある理由:Session は新フィルターの対象として screenshot-stitching app を明示し、
.screenshotsでアルバム全体から探すコストを下げられます。 - 始め方:
PHPickerConfigurationを作成しconfiguration.filter = .screenshotsを設定、PHPickerViewControllerまたは SwiftUIPhotosPickerで表示する。
2. スクリーンショット除外のアバター選択器
- やること:プロフィールページで通常写真のみからアバターを選び、スクリーンショットを自動除外する。
- 価値がある理由:アバター選択にスクリーンショットは通常不要。
allとnotでルールを選択器自体に書けます。 - 始め方:
.all(of: [.images, .not(.screenshots)])をフィルターに使い、選択変化後にPhotosPickerItemをオンデマンド読み込みする。
3. クロスプラットフォームのプロフィール画像編集
- やること:iOS と macOS のプロフィールページで SwiftUI
PhotosPicker選択ロジックを共有する。 - 価値がある理由:Session デモでは同じ SwiftUI コードが iOS と macOS でコンパイルでき、watchOS も同 API をサポートします。
- 始め方:view model に
PhotosPickerItembinding を保持し、ビューでPhotosPicker(selection:matching:)をトリガー、Transferable で画像を読み込む。
4. 大容量動画向けインポートフロー
- やること:動画編集 App で素材選択後、項目ごとに読み込み状態を表示し、結果を App 管理ディレクトリに保存する。
- 価値がある理由:Session は大動画のダウンロードに時間がかかることを提醒し、全データを一度にメモリへ載せるのは現実的ではありません。
- 始め方:
FileTransferRepresentationでファイルとして読み込み、受信後すぐ App ディレクトリへコピーし、削除タイミングを管理する。
5. Mac メディア App の二重入口選択
- やること:写真ライブラリアセットはデフォルトで Photos picker、ファイルシステム素材は
NSOpenPanelを維持する。 - 価値がある理由:Session はメディア系 macOS App に新 Photos picker をデフォルト推奨しますが、ライブラリ外ファイルも必要な場合があります。
- 始め方:メディアライブラリ入口に AppKit
PHPickerViewController、ファイル入口はNSOpenPanelを継続し、ライブラリ選択後は App 管理場所へコピーする。
関連セッション
- Meet the new Photos picker — iOS 14 で初めて
PHPickerViewControllerが導入され、完全な写真ライブラリ権限なしで写真と動画を選べる仕組みを説明します。 - Improve access to Photos in your app — iOS 15 の Photos 権限モデル、Limited Library、PHPicker 設定改善を解説します。
- Meet Transferable — SwiftUI の Transferable プロトコルを紹介。
PhotosPickerItemのデータ読み込みで使う転送モデルを理解できます。 - Discover PhotoKit change history — 選択以外で写真ライブラリ変化を追跡する必要がある場合、persistent change history を解説します。
- Embed the Photos Picker in your app — WWDC 2023 で Photos Picker が拡張され、埋め込み選択器とより多くの SwiftUI オプションが追加されました。
コメント
GitHub Issues · utterances