PHPickerViewController で選択した順番通りに PHAsset を取得する方法
こんにちは!アルダグラム でエンジニアをしている渡辺です。
今回は、iOS アプリ開発で写真や動画を扱う際によく使う PHPickerViewController を使って、ユーザーが選択した順番通りに PHAsset を取得する方法について紹介します。私自身、開発中に少しつまずいたポイントもあるので、同じ問題に直面した方の参考になれば嬉しいです!
📸 KANNA アプリのアップロード機能
私たちが開発しているアプリ KANNA では、複数の写真や動画を選択し、選択した順番通りにアップロード する機能があります。この機能を実装する際、写真選択後の順序保持が思ったよりも厄介だったので、その解決策を共有します。
🛠 PHPickerViewController の選択順序
PHPickerViewController には、写真選択時の挙動を制御するための PHPickerConfiguration があります。その中に Selection という便利な Enum があり、これを使うと選択順序を制御できます。
var configuration = PHPickerConfiguration()
configuration.selection = .ordered
この設定を使うと、選択した順番通りに PHPickerResult の配列が返されます。
🚩 PHAsset の取得で順番が崩れる問題
ただし、PHPickerResult から assetIdentifier を使って PHAsset を取得すると、問題が発生します。
let identifiers = results.compactMap { $0.assetIdentifier }
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
上記のコードでは、PHFetchResult<PHAsset> の取得順序が選択順と一致しません。これは PHFetchResult が順序保証されないためです。その結果、せっかく PHPickerResult で選択順が保持されていたのに、PHAsset を取得した段階で順序が崩れてしまいます。
✅ 解決策:PHAsset を再ソート
この問題を解決するには、PHPickerResult の選択順と取得した PHAsset を突き合わせて再ソートすればOKです。
func getOrderedAssets(from results: [PHPickerResult]) -> [PHAsset] {
let identifiers = results.compactMap { $0.assetIdentifier }
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
// identifier -> PHAsset の配列を作成
var assetList: [PHAsset] = []
fetchResult.enumerateObjects { asset, _, _ in
assetList.append(asset)
}
// PHPickerResult の順番に PHAsset を再構成
return identifiers.compactMap { identifier in
assetList.first { $0.localIdentifier == identifier }
}
}
この関数では:
PHPickerResultからassetIdentifierを抽出PHAsset.fetchAssetsで一括取得identifierをキーにPHAssetを配列化PHPickerResultの順番に配列からPHAssetを再構成
この方法なら、選択した順番通りの PHAsset の配列を安全に取得できます!
🎯 まとめ
PHPickerViewController を使った写真選択では、selection = .ordered を使うことでユーザーの選択順を取得できます。ただし、PHAsset の取得時に順番が崩れるので、取得後に再ソートすることで解決します。
質問や改善点があれば、ぜひコメントやフィードバックお待ちしています! 🚀
もっとアルダグラムエンジニア組織を知りたい人、ぜひ下記の情報をチェックしてみてください!
株式会社アルダグラムのTech Blogです。 世界中のノンデスクワーク業界における現場の生産性アップを実現する現場DXサービス「KANNA」を開発しています。 採用情報はこちら: herp.careers/v1/aldagram0508/
Discussion