PHPickerViewController を使用して画像と動画を選択しています。私のアプリはファイルを保存し、iOS 以外のアプリケーションで使用するため、ライブフォトの使用には興味がありません。現時点では、次の 2 つのチュートリアルを組み合わせた livePhoto から画像を抽出するために次の方法を使用しています。
https://www.appcoda.com/phpicker/
https://www.limit-point.com/blog/2018/live-photos/
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
if results != nil {
for result in results! {
let itemProvider = result.itemProvider
guard let typeIdentifier = itemProvider.registeredTypeIdentifiers.first,
let utType = UTType(typeIdentifier)
else { continue }
if utType.conforms(to: .image) {
self.getPhoto(from: itemProvider, isLivePhoto: false)
} else if utType.conforms(to: .movie) {
self.getVideo(from: itemProvider, typeIdentifier: typeIdentifier)
} else {
self.getPhoto(from: itemProvider, isLivePhoto: true)
}
}
}
}
private func getPhoto(from itemProvider: NSItemProvider, isLivePhoto: Bool) {
let objectType: NSItemProviderReading.Type = !isLivePhoto ? UIImage.self : PHLivePhoto.self
if itemProvider.canLoadObject(ofClass: objectType) {
itemProvider.loadObject(ofClass: objectType) { object, error in
if let error = error {
print(error.localizedDescription)
}
if !isLivePhoto {
if let image = object as? UIImage {
DispatchQueue.main.async {
// use image
}
}
} else {
if let livePhoto = object as? PHLivePhoto {
DispatchQueue.main.async {
let livePhotoResources = PHAssetResource.assetResources(for: livePhoto)
for resource in livePhotoResources {
if resource.type == .photo {
let buffer = NSMutableData()
var dataRequestID:PHAssetResourceDataRequestID = PHInvalidAssetResourceDataRequestID
let options = PHAssetResourceRequestOptions()
options.isNetworkAccessAllowed = true
dataRequestID = PHAssetResourceManager.default().requestData(for: resource, options: options, dataReceivedHandler: { (data:Data) in
buffer.append(data)
}, completionHandler: { (error:Error?) in
// buffer now contains the resource data
if let image = UIImage(data: buffer as Data) {
// use image
}
})
}
}
}
}
}
}
}
}
このアプローチはうまくいくようで、写真と livePhoto の両方の UIImage を取得できます。
これについてもっと簡単な方法があるかどうか疑問に思っていますか?PHPickerViewController のプレビューは単なる画像なので、livePhoto の画像リソースを直接抽出できますか?
また、ピッカーは次のように定義されています。
var config = PHPickerConfiguration()
config.filter = .any(of: [.images, .videos, .livePhotos])
config.selectionLimit = 10
config.preferredAssetRepresentationMode = .current
let controller = PHPickerViewController(configuration: config)
livePhotos なしでフィルターを定義するだけで、livePhotos が表示され、uiType.conforms(to: .image) が livePhotos に対して true を返すようになることを期待していましたが、そうではありませんでした。