web-dev-qa-db-ja.com

iOSデバイスで利用可能な最大のPHAsset画像サイズを決定する

IOSデバイスで利用可能な最大のPHAsset画像サイズを決定するにはどうすればよいですか?「利用可能」とは、iCloudフォトライブラリからネットワークをダウンロードする必要がなく、現在デバイス上にあることを意味しますか?

私はサムネイルのコレクションがUICollectionViewに表示されるアプリを開発してきました(写真アプリによく似ています)。その後、ユーザーは画像を選択してフルサイズで表示できます。フルサイズの画像は、必要に応じてiCloudからダウンロードされます。ただし、フルサイズが利用可能になるまで、可能な限り最大のバージョンの画像をユーザーに表示したいと思います。

写真フレームワークの動作はかなり奇妙です。

コレクションビューでは、PHCachingImageManagerから cache (およびそれ以降 request )の画像を使用しており、targetSizeは186x186ピクセル(網膜のスケーリングのため、UICollectionViewCellの寸法を2倍にします)。

これは非常にうまく機能し、スクロールが非常に速く、セルに画像を入力するのに遅れがありません。返された画像のサイズを確認すると、それらはすべておよそ342x256ピクセルです。これは、iCloudフォトライブラリが有効で「ストレージの最適化」が有効になっているiPhone 6にあるため、ほとんどの画像のデバイスには小さなサムネイルのみが保存されます。

ただし、奇妙な部分は、 PHImageRequestOptionsDeliveryMode.Opportunistic を使用してPHCachingImageManagerまたはPHImageManager.defaultManager()を使用して、任意の画像のフルサイズ(またははるかに大きい)バージョンを要求した場合です。オプションの場合、返される最初の(低品質の)画像は、フルスクリーンでひどく見える小さな60x45ピクセルの切手で、最終的にはフルサイズの画像がダウンロードされて置き換えられます。

明らかにそこにareコレクションビューに表示されたばかりの大きなサムネイル(342x256)がすでにデバイスにあります!では、フルサイズがダウンロードされるまで、なぜ最初の「低品質」画像として返されないのでしょうか。 342x256イメージが実際にデバイス上にあることを確認するために、コードを機内モードで実行したため、ネットワークアクセスは発生しませんでした。

私が見つけたのは、256x256までのサイズをリクエストすると、342x256の画像が返されるということでした。大きくすると(1ピクセルでも)、最初に60x45の画像が返され、次にフルサイズの画像をダウンロードしようとします。

最初に256x256リクエストを作成し、次にPHImageRequestOptionsDeliveryMode.HighQualityFormat(小さな中間画像を返さない)を使用したフルサイズリクエストを作成するようにコードを変更しました。これは問題なく機能します。また、iOSフォトアプリは、画像全体をダウンロードしている間、比較的高品質のサムネイルを表示するため、これを実行する必要があります。

それで、その背景で、どうすればPHAssetのデバイスイメージサイズの最大値を知ることができますか? 256x256はマジックナンバーですか、それともiCloud Photo Libraryがスペースを最適化する方法(ライブラリのサイズと利用可能なデバイスストレージに基づく)に依存しますか?

確かに、Photos Frameworkが現在利用可能な最大の画像を返さない(現在のサイズよりも大きいサイズを要求された場合)というバグのように思われます。また、最大サイズを取得するには、そのサイズ以下を要求する必要があります。もっと大きいものを求めると、60x45のミニチュアが手に入るからです。奇妙な。

UPDATE:Appleに提出されたバグレポート: https://openradar.appspot.com/25181601
バグを示すサンプルプロジェクト: https://github.com/mluisbrown/PhotoKitBug

50
mluisbrown

質問に投稿されたサンプルプロジェクトを使用すると、シミュレーターで問題を再現できましたが、次の変更を行うと、最大の画像しか表示されませんでした。

let targetSize = PHImageManagerMaximumSize
1
markwatsonatx

実際、AppleがPHImageResultIsDegradedKey = 1で劣化した45 * 60画像を返す理由はわかりません。私にとっては、最初にdeliveryModePHImageRequestOptionsDeliveryModeHighQualityFormatで256 * 256画像をリクエストします。他のPHImageRequestOptionsを使用して、以下のようなフルサイズの画像をリクエストします。

PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.networkAccessAllowed = YES;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info){
// code to update the iCloud download progress
});

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
// code to update UIImageView or something else.
});

そして、Instagramはこの同様のソリューションを使用してiCloudからの画像を処理しているのではないかと思います。

0
Chris Forever