我找不到太多关于使用异步等待的 PHPickerViewControllerDelegate didFinishPicking 函数的文档,并且我不确定我是否了解如何使用 NSItemProvider。这是我的委托代码:
func picker( _ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]){
for result in results {
Task {
if result.itemProvider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
do {
let url = try await result.itemProvider.loadItem(forTypeIdentifier: UTType.image.identifier) as! URL
print(url.description)
let data = try Data(contentsOf: url)
let image = UIImage(data: data)
}
catch {
print(error)
}
}
}
}
}
在模拟器中使用时,ItemProvider 返回一个 URL,但该 URL 的数据内容为空。如何从 ItemProvider 获取图像?谢谢
正如您在评论中被告知的那样,在这里使用
loadDataRepresentation
是一个更好的主意。正如您所说,没有 async
版本的 loadDataRepresentation
— 但您可以通过扩展 NSItemProvider 来编写一个版本:
import Foundation
import UniformTypeIdentifiers
extension NSItemProvider {
/// Injected method that abstracts image data loading and makes it async/await.
/// - Returns: The data.
func loadImageData() async throws -> Data {
enum ImageLoadingError: Error {
case unknown
}
return try await withCheckedThrowingContinuation { continuation in
self.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { data, error in
if let data {
continuation.resume(returning: data)
} else {
continuation.resume(throwing: error ?? ImageLoadingError.unknown)
}
}
}
}
}
现在你的 PHPickerViewControllerDelegate 方法可以调用它,如下所示:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true) {
Task { @MainActor in
guard let result = results.first else { return }
let provider = result.itemProvider
let data = try await provider.loadImageData()
// do something with the data here
}
}
}