PHPickerViewController使用异步等待委托加载项

问题描述 投票:0回答:1

我找不到太多关于使用异步等待的 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 获取图像?谢谢

ios swift phpickerviewcontroller
1个回答
0
投票

正如您在评论中被告知的那样,在这里使用

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
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.