PhotoKitは、iOSおよびmacOSでメディアライブラリを操作するためのAppleのフレームワークであり、デバイス上の写真、ビデオ、Live Photosへの直接アクセスを提供します。Appleのドキュメントによると、このフレームワークは従来のAssetsLibraryを置き換え、iCloud、アルバム、編集、Change Trackingをサポートしています。PhotoKitは、iCloudによる自動同期を備えた、クエリ、キャッシュ、メディアライブラリ変更のための統一APIを提供します。
重要なポイント
PhotoKitは、Appleのフレームワーク(iOS 8、macOS 10.11で導入)で、システムメディアライブラリを操作するためのオブジェクト指向APIを提供します。AssetsLibraryとは異なり、PhotoKitはメディアライブラリをデータベースとして扱います。クエリはPHAsset、PHCollection、PHCollectionListオブジェクトを返し、コンテンツとストレージ構造を表します。
PhotoKitはすべてのメディアタイプをサポートしています:写真(JPEG、HEIF、RAW)、ビデオ(MOV、MP4)、Live Photos、バーストショット。フレームワークは自動的にiCloud同期を管理します。画像がiCloudに保存されている場合、PhotoKitはネットワーク経由でそれを要求し、PHImageRequestOptions.progressHandlerを介して進捗を報告します。
PhotoKitの重要な特徴は、セッション間で安定したローカル識別子(localIdentifier)を持つPHObjectベースのデータモデルです。これにより、メディアオブジェクトへの参照を保存し、アプリ再起動後に再クエリすることなく復元できます。
PhotoKitは3つのレベルで構成されています:データモデル(PHObject)、クエリ(PHFetchResult)、変更(PHPhotoLibrary.performChanges)。データモデルは階層的です。PHAsset(写真/ビデオ)はPHAssetCollection(アルバム)内に存在し、アルバムはPHCollectionList(フォルダ)にグループ化されます。
クエリはPHAsset.fetchAssetsとPHAssetCollection.fetchAssetCollectionsを介して実行されます。すべてのfetchメソッドは同期型で、PHFetchResultを返します。これは即座にメディアライブラリデータベースに対してクエリを実行します。PHFetchResultはインデックスによる高速アクセス(object(at:))とenumerateObjectsによる列挙をサポートします。
PHFetchOptionsはクエリを設定するためのオブジェクトです:並べ替え(sortDescriptors)、述語(predicate)、非表示および削除されたメディアの包含(includeHiddenAssets、includeAllBurstAssets)。Fetchオプションを使用すると、メディアタイプでフィルタリングできます:PHAssetMediaType.image、.video、.audio。
PhotoKitには、メディアライブラリへのアクセス、クエリ、変更のための一連のクラスが含まれています。フレームワークを効果的に使用するには、それぞれを理解することが不可欠です。
PHAssetは単一のメディアアイテムを表す不変オブジェクトです。メタデータを含みます:mediaType、mediaSubtypes、creationDate、location、pixelWidth、pixelHeight、duration(ビデオ用)、isFavorite、burstIdentifier。localIdentifierは、アプリ再起動後もアクセス可能な安定した文字列キーです。
PHAssetCollectionはメディアのグループです:システムアルバム(Recents、Favorites、Selfies、Screenshots)、ユーザーアルバム、またはMoments(時間と場所で自動グループ化)。属性:localizedTitle、assetCollectionType、assetCollectionSubtype、startDate、endDate。
PHCollectionListは、アルバム(PHAssetCollection)や他のフォルダを含むフォルダです。主にユーザーインターフェースで階層を表示するために使用され、あまり頻繁には使われません。
PhotoKitはPHAssetから直接UIImageを返しません — PHImageManagerを介して画像を要求する必要があります。これにより、iCloudサポート、キャッシュ、必要なサイズで画像が読み込まれることが保証されます。
| コンポーネント | 目的 | 特徴 |
|---|---|---|
| PHImageManager.default() | 単発リクエスト用の標準マネージャ | リクエスト間のキャッシュなし |
| PHCachingImageManager | コレクション用のプリロード付きマネージャ | スムーズスクロールのためのstartCachingImages |
| PHImageRequestOptions | リクエスト設定:サイズ、モード、配信 | synchronous、deliveryMode、progressHandler |
| PHImageRequestID | キャンセル用のリクエスト識別子 | cancelImageRequest(PHImageRequestID) |
PHImageManagerは3つの配信モードをサポートしています:opportunistic(最初に縮小版、次にフルサイズ)、highQualityFormat(フル品質のみ)、fastFormat(最速の利用可能バージョン)。コレクションの場合は、常に可視セル用の画像プリロード付きPHCachingImageManagerを使用してください。
PhotoKitは、カスタムギャラリー、エディタ、メディアアプリケーションの作成に使用されます。3つの主要なシナリオを見てみましょう。
作成日でソートされたPHFetchOptionsを使用したPHAsset.fetchAssetsは、カスタムフォトギャラリーを構築するための基本的なクエリです。PHFetchResultは遅延ロードとストリーミングアクセスをサポートします。
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(
key: "creationDate",
ascending: .false
)]
options.predicate = NSPredicate(
format: "mediaType == %d",
PHAssetMediaType.image.rawValue
)
let allPhotos = PHAsset.fetchAssets(with: options)
print("\(allPhotos.count)枚の写真が見つかりました")
allPhotos.enumerateObjects { asset, index, stop in
print("写真\(index): \(asset.localIdentifier)")
}
PHFetchResultはスレッドセーフなコンテナです。object(at:)を介したインデックスによるオブジェクトへのアクセスはUIをブロックしませんが、PHImageManagerを介した画像リクエストは非同期で行う必要があります。
PHCachingImageManagerは、プリロード用のstartCachingImagesメソッドとstopCachingImagesメソッドを持つPHImageManagerのサブクラスです。スムーズスクロールのためにUICollectionViewで使用されます。
let cachingManager = PHCachingImageManager()
let targetSize = CGSize(width: 200, height: 200)
// 表示セルのプリロード
cachingManager.startCachingImages(
for: visibleAssets,
targetSize: targetSize,
contentMode: .aspectFill,
options: nil
)
// iCloudフォールバック付きPHImageRequestOptionsを介した画像リクエスト
let requestOptions = PHImageRequestOptions()
requestOptions.deliveryMode = .opportunistic
requestOptions.isNetworkAccessAllowed = .true
requestOptions.progressHandler = { progress, error, stop, info in
DispatchQueue.main.async {
print("iCloudからダウンロード中: \(progress * 100)%")
}
}
let requestID = cachingManager.requestImage(
for: asset,
targetSize: targetSize,
contentMode: .aspectFill,
options: requestOptions
) { image, info in
print("画像を取得しました: \(image?.size ?? .zero)")
}
メディアライブラリへの変更は、changeRequestブロック内でPHPhotoLibrary.shared().performChangesを介して実行されます。すべての操作はバッチ処理され、トランザクションとして適用されます。
PHPhotoLibrary.shared().performChanges {
let changeRequest = PHAssetChangeRequest(for: asset)
changeRequest.isFavorite = .true
} completionHandler: { success, error in
if success {
print("お気に入りに追加されました")
}
}
PhotoKitは、PHPhotoLibraryChangeObserverプロトコルを通じてメディアライブラリの変更を監視するメカニズムを提供します。変更(作成、削除、編集)が発生すると、PHChangeオブジェクトを伴ってphotoLibraryDidChangeメソッドが呼び出されます。
PHChangeには、クエリタイプごとのchangeDetailsが含まれます:PHFetchResultChangeDetailsにはremovedIndexes、insertedIndexes、changedIndexesが含まれます。これにより、UICollectionViewのperformBatchUpdates(move、insert、delete)を使用して、アニメーション付きでUIに変更を適用できます。
class PhotosViewController: UIViewController {
var fetchResult: PHFetchResult>PHAsset>?
override func viewDidLoad() {
super.viewDidLoad()
PHPhotoLibrary.shared().register(self)
}
deinit {
PHPhotoLibrary.shared().unregisterChangeObserver(self)
}
}
extension PhotosViewController: PHPhotoLibraryChangeObserver {
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let fetchResult,
let details = changeInstance.changeDetails(for: fetchResult)
else { return }
DispatchQueue.main.async {
self.fetchResult = details.fetchResultAfterChanges
// collectionViewに変更を適用
}
}
}
PhotoKitは、PHContentEditingInputとPHContentEditingOutputのメカニズムを通じてメディア編集をサポートします。アプリは元のデータとともにeditingInputを要求し、変更を適用して、editingOutputを介して結果を保存します。フレームワークは自動的にオリジナルを保持し、ユーザーはオリジナルにリセットして変更を元に戻すことができます。
RAW写真(DNG、CR2、NEF)は、元のRAWファイルへのアクセスを提供するPHAssetResourceManagerを介してサポートされています。RAW処理には、温度、露出、シャープネスの調整をサポートするCIRAWFilterフィルタとともにCoreImageを使用することをお勧めします。PhotoKitはPhoto Editing Extension(iOS)を介したエディタ拡張機能もサポートしています — 選択した写真やビデオを処理するために、システムエディタからアプリを呼び出すことができます。
PhotoKitは強力ですがリソースを多く消費するフレームワークです。誤った使用はスクロールの遅延や過剰なメモリ消費につながる可能性があります。最適なパフォーマンスを得るために、次の推奨事項に従ってください。
PHLivePhotoは、PHLivePhoto.request(with:targetSize:contentMode:options:resultHandler:)を介した個別のリクエストが必要です。写真のみを表示するセルにはLive Photoを要求しないでください — 表示用にPHLivePhotoBadgeを使用してください。
よくある質問
PhotoKitは、iOS 8で導入された、メディアライブラリを操作するためのAppleの最新フレームワークです。従来のAssetsLibraryとは異なり、PhotoKitはPHAssetオブジェクトモデル、高速検索付きPHFetchResult、iCloudサポート、変更監視のためのChange Trackingを提供します。
コールバックハンドラ付きでPHPhotoLibrary.requestAuthorization(for: .readWrite)を呼び出します。.authorizedステータスを受け取った後、PHAsset.fetchAssetsクエリを実行できます。書き込みアクセスには.readWrite権限が必要です。読み取り専用の場合は.addOnlyです。
パラメータ(asset、targetSize、contentMode、PHImageRequestOptions)を指定してPHImageManager.default().requestImageを使用します。非同期メソッドはPHImageRequestIDを返し、リクエストをキャンセルできます。コレクションの場合は、プリロード付きPHCachingImageManagerを使用してください。
PHPhotoLibrary.shared().register(self)を介してオブザーバを登録し、PHPhotoLibraryChangeObserverプロトコルを実装します。photoLibraryDidChangeメソッドで、各fetchResultのchangeDetailsを持つPHChangeを受け取り、アニメーション付きでUIに変更を適用します。
PHImageRequestOptionsで、isNetworkAccessAllowed = trueとiCloudダウンロード進捗を追跡するprogressHandlerを設定します。高速スクロール中はネットワークアクセスを無効にし、スクロール遅延を避けるためにローカルバージョンのみを読み込みます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。