はじめに
写真アプリで「フォトライブラリから写真を複数同時に取り込む機能」を実装しようとした際に、
こちらの記事を参考にしたのですが、ハマったことがあったので、記事にしてみようと思いました。
ハマった点は以下の3点です。
- 単純に複数画像を選択するだけなら「imageManager.requestImage」を使えばいいのですが、この場合選択した画像がかなり低画質になってしまい使い物にならなかった。
- Storyboadを使わずにコードでUIを設定していたので他の機能を追加しづらかった。
- 長押しドラッグ(?)で複数選択ができない。(未実装)
本題
基本的なことは元ネタの記事を見てください。
また、元ネタの記事同様コードが長く重すぎるのでコードはGitHubに公開しておきました。
https://github.com/YoshihisaTanaka-prog/PhotosMultiSelect
変更点
高画質化
まず、以下の部分を以下に書き換えました。
LibraryPhotoViewController.swift(before) (220-230行目付近)
imageManager.requestImage(for: asset, targetSize: thumbnailSize, contentMode: .aspectFill, options: nil, resultHandler: { image, _ in
if image == nil {
print("managerError")
} else {
self.items.append(image! as UIImage)
}
})
LibraryPhotoViewController.swift(after) (220-230行目付近)
imageManager.requestImageDataAndOrientation(for: asset, options: nil, resultHandler: { data, _, _, _ in
if data == nil {
print("managerError")
} else {
if let image = UIImage(data: data!){
self.items.append(image)
if(self.items.count == indexPaths.count){
self.mainView.items = self.items
self.mainView.photoCollectionView.reloadData()
self.dismiss(animated: true, completion: nil)
}
}
}
})
しかし、このまま状態では非同期処理を行うためメインの画面に全く反映されなかったので「DispatchQueue.main.async」を追加しました。
LibraryPhotoViewController.swift(add DispatchQueue) (220-230行目付近)
imageManager.requestImageDataAndOrientation(for: asset, options: nil, resultHandler: { data, _, _, _ in
if data == nil {
print("managerError")
} else {
if let image = UIImage(data: data!){
DispatchQueue.main.async {
self.items.append(image)
if(self.items.count == indexPaths.count){
self.mainView.items = self.items
self.mainView.photoCollectionView.reloadData()
self.dismiss(animated: true, completion: nil)
}
}
}
}
})
(追記2022-09/29)
このままでは画像の順番がバラバラになってしまうのでもう少し修正しておきました。
詳しくはGitHubのコードを見てください。一応大まかに何をしたのかを書いておきます。
- 同期処理部分にUIImage配列の要素を追加するようにし、非同期部分にindexを送りその部分を上書きするようにしました。
- 全てを上書きしたかどうかを確認するためのBoolean配列を作り、上書きが全て完了した時点で最初の画面に戻るようにしました。
(ここまで追記です)
これでうまく動くようになりました。
Storyboadの対応
Storyboadへの対応は特筆すべき点はありません。
長押しドラッグ選択の対応
未実装です。