はじめに
この記事は iOS Advent Calendar 2020 の 14 日目の記事です。
私が開発してるアプリは iOS 7 をサポートしていた時期もあり、 ALAsset が使われている画面もあります。この ALAsset は端末内の写真やビデオを扱うためのクラスで、現在は PHAsset に置き換わっているため Deprecated になっています。 このクラスが iOS 14 からいよいよサポートされなくなってるなと感じるバグが発生し修正作業に追われたため、この記事を残します。
発生した現象
この問題が発生したのは写真一覧画面でした。 この画面では写真ライブラリにアクセスするため、 iOS 13 以前ではアクセス時に写真ライブラリの使用を許可するか聞かれるダイアログが表示されており、
- OK
- 許可しない
の選択肢がありました。 iOS 14 ではこのアクセスレベルが変更されており、
- 選択した写真のみ
- すべての写真
- なし
の選択肢が表示されます。この選択肢の「すべての写真」を選ぶと写真ライブラリに保存されている全ての写真を表示することができ、「なし」を選ぶと1枚も写真が表示されないことは確認しました。が、「選択した写真のみ」を選んだにも関わらず、この画面では選んだ写真を表示することができませんでした(写真のパスを取得することはできる)。
ちなみに、この問題は Xcode 12 でビルドしていなくても、 iOS 14 端末で動かすと必ず発生します。ですので知らない間に影響を受けてる可能性があるので、 ALAsset を使っている方は一度確かめてみるのが良いと思います(「すべての写真」を選んでれば影響を受けないので、クリティカルな問題では無いと思いますが)。
原因
コードを追っていくと、
CGImage *cgImage = [asset thumbnail];
self.imageView.image = [UIImage imageWithCGImage:cgImage];
上記のコードの cgImage が nil になっていることがわかりました。「すべての写真」を選んでいると thumbnail メソッドで画像を取得することができていましたが、「選択した写真のみ」を選んでいると取得できなくなっていました。
この thumbnail メソッドについて Apple のドキュメントを呼んでみると、「 This method returns NULL for assets from a shared photo stream that are not yet available locally. (このメソッドは、まだローカルで利用できない共有フォトストリームからのアセットに対してNULLを返します。)」
と書かれていました。ここの判定がそれぞれの選択肢を選んだときで変わったみたいですね。
解決方法
PHAsset に置き換えましょう!!!
一応、
CGImage *cgImage = [[asset defaultRepresentation] fullResolutionImage];
self.imageView.image = [UIImage imageWithCGImage:cgImage];
とすることで画像を取得できることは確認しましたが、わかりにくいやり方ですし Deprecated を無理矢理しのぐのは今後またバグになる可能性が高いです。幸い私は別 ViewController で PHAsset を使っている画面があったので、その画面に置き換えることで対応しました。
まとめ
ということで、 iOS 14 になったことで知らない間に ALAsset を使っていた画面で写真が表示できなくなっていた、という記事を書きました。今時 ALAsset を使っている方がどのくらいいるのかわかりませんが、同じような境遇の方の助けになっていましたら幸いです。
以上で、 14 日目の記事は終了します。ありがとうございました!!