iOS 14: PHPickerViewController 有没有办法同时加载所有资源 PHPickerResult
iOS 14: PHPickerViewController is there any way to load all assets at the same time PHPickerResult
目前,我正在尝试深入研究 PHPickerViewController,以便同时从照片中获得 select 多个图像。所以我想要用户 selected 的图像数组,我尝试了太多方法但没有运气。这是我的代码,请告诉我有最佳实践吗?
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: nil)
var images: [UIImage?] = []
var totalConversionsCompleted = 0
for (index,result) in results.enumerated() {
result.itemProvider.loadObject(ofClass: UIImage.self, completionHandler: { (object, error) in
let image = object as? UIImage
images.append(image)
totalConversionsCompleted += 1
if totalConversionsCompleted == index {
print("completion happen \(images)")
}
})
}
}
1 - 您是否将控制器设置为 PHPickerViewController 的委托?
为此,您的控制器应符合 PHPickerViewControllerDelegate
class ViewController: UIViewController, PHPickerViewControllerDelegate {
并且您应该将控制器设置为 PHPickerViewController
的委托
pickerController.delegate = self //if you create PHPickerViewController inside your viewController
然后你会得到这个方法的结果
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
2 - 如果您无法获得多项选择,您可以更改与 PHPickerViewController 一起使用的 PHPickerConfiguration 对象的选择限制
var confing = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
confing.selectionLimit = 5
let pickerController = PHPickerViewController(configuration: confing)
3 - 然后您可以使用 results array
中的对象
let identifiers = results.compactMap(\.assetIdentifier)
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
我使用单个 DispatchGroup
让它工作。这是我的委托方法实现:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true) // dismiss a picker
let imageItems = results
.map { [=10=].itemProvider }
.filter { [=10=].canLoadObject(ofClass: UIImage.self) } // filter for possible UIImages
let dispatchGroup = DispatchGroup()
var images = [UIImage]()
for imageItem in imageItems {
dispatchGroup.enter() // signal IN
imageItem.loadObject(ofClass: UIImage.self) { image, _ in
if let image = image as? UIImage {
images.append(image)
}
dispatchGroup.leave() // signal OUT
}
}
// This is called at the end; after all signals are matched (IN/OUT)
dispatchGroup.notify(queue: .main) {
print(images)
// DO whatever you want with `images` array
}
}
目前,我正在尝试深入研究 PHPickerViewController,以便同时从照片中获得 select 多个图像。所以我想要用户 selected 的图像数组,我尝试了太多方法但没有运气。这是我的代码,请告诉我有最佳实践吗?
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: nil)
var images: [UIImage?] = []
var totalConversionsCompleted = 0
for (index,result) in results.enumerated() {
result.itemProvider.loadObject(ofClass: UIImage.self, completionHandler: { (object, error) in
let image = object as? UIImage
images.append(image)
totalConversionsCompleted += 1
if totalConversionsCompleted == index {
print("completion happen \(images)")
}
})
}
}
1 - 您是否将控制器设置为 PHPickerViewController 的委托?
为此,您的控制器应符合 PHPickerViewControllerDelegate
class ViewController: UIViewController, PHPickerViewControllerDelegate {
并且您应该将控制器设置为 PHPickerViewController
的委托pickerController.delegate = self //if you create PHPickerViewController inside your viewController
然后你会得到这个方法的结果
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
2 - 如果您无法获得多项选择,您可以更改与 PHPickerViewController 一起使用的 PHPickerConfiguration 对象的选择限制
var confing = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
confing.selectionLimit = 5
let pickerController = PHPickerViewController(configuration: confing)
3 - 然后您可以使用 results array
中的对象let identifiers = results.compactMap(\.assetIdentifier)
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
我使用单个 DispatchGroup
让它工作。这是我的委托方法实现:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true) // dismiss a picker
let imageItems = results
.map { [=10=].itemProvider }
.filter { [=10=].canLoadObject(ofClass: UIImage.self) } // filter for possible UIImages
let dispatchGroup = DispatchGroup()
var images = [UIImage]()
for imageItem in imageItems {
dispatchGroup.enter() // signal IN
imageItem.loadObject(ofClass: UIImage.self) { image, _ in
if let image = image as? UIImage {
images.append(image)
}
dispatchGroup.leave() // signal OUT
}
}
// This is called at the end; after all signals are matched (IN/OUT)
dispatchGroup.notify(queue: .main) {
print(images)
// DO whatever you want with `images` array
}
}