🏙️

【Swift】複数写真の並列処理読み込みは難しい

2022/05/17に公開

追記

これはiOS 16から使えるPhotosPickerでも同様

先に結論

NSItemProvider.loadObject(ofClass:) async throwsは並列処理(withThrowingTaskGroupなど)で処理しないようにする。

5枚以上程度同時に並列でデータ読み込みloadObject(ofClass:)を行うと処理が終わらなくなってしまうため。

原因はメモリ?かもしれない(MacだとiPhoneより多く並列処理できるため)

写真の選択と読み込み

通常iOS/iPadOSではPHPickerViewControllerなどを使用して写真(画像,動画)を選択して、アプリ側に写真の情報(PHPickerResult)を渡して、その情報をもとに写真データを読み込みます。
この時に複数の写真を選択することが可能です。

写真の読み込み方法

写真データの読み込みには情報(PHPickerResult)のitemProvider(NSItemProvider)のloadObject(ofClass:) async throwsを使って非同期に読み込みます。

複数写真の読み込み

複数写真を選択した際に、いい感じに写真データを読み込みたいのですが、いくつかの案があります。

  1. 選択後に全ての写真データを順番に非同期で読み込む
  2. 選択後に全ての写真データを並列非同期で読み込む
  3. onAppear(SwiftUI), viewWillAppear(UIKit)でViewが表示された際に、写真データを読み込む(表示されなければ読み込まない)

各問題点

  1. 選択写真が多すぎると時間がかかる。
  2. 同時に5枚以上?程度並列で写真データを読み込むと処理が終わらなくなる。
  3. onAppear(SwiftUI), viewWillAppear(UIKit)が同時に起こると2と同じ問題になってしまい、処理が終わらなくなる。

5枚以上並列並列読み込みできない問題

上で挙げたように、なぜか5枚以上程度(メモリ次第?)写真データを並列でloadObject(ofClass:) async throwsすると処理が終わらなくなってしまいます。エラーの返してくれずに、処理が終わらない形になってしまいます。

これを正しくタイムアウトや制限処理などをする方法がわからないので、上の2, 3は諦めます。

結論

写真データの読み込みは普通に順番に非同期で読み込む。
並列処理でやっても余程の数でなければ気になる時間ではないので、あきらめましょう

諦めない方法があれば教えてください。

実装方法

https://zenn.dev/zunda_pixel/articles/00f149787bed86

Discussion