我在使用完成处理程序的结果时遇到问题。 我收到此错误“无法将类型 '()' 的值转换为预期的参数类型”
struct SearchCollectionViewModel {
let name: String
let previewURL: String?
var image:UIImage?
let dataController = DataController()
}
extension SearchCollectionViewModel {
init(with result: Result) {
self.name = result.trackName
self.previewURL = result.previewURL
if let url = result.previewURL {
let imgData = preview(with: url, completion: { data -> Data? in
guard let data = data as? Data else { return nil }
return data
})
self.image = UIImage(data: imgData)
}
}
private func preview(with url: String, completion: @escaping (Data) -> Data?) {
dataController.download(with: url) { data, error in
if error == nil {
guard let imageData = data else { return }
DispatchQueue.main.async {
_ = completion(imageData)
}
}
}
}
}
最佳答案
一些观察结果:
您无法“返回”通过转义闭包异步检索的值。
闭包定义
(Data) -> Data?
表示关闭不仅会通过Data
检索图像,但闭包本身会将某些内容返回到preview
。但它显然没有这样做(因此需要_
,如_ = completion(...)
)。我建议您将其更改为(Data?) -> Void
(或使用Result<T, U>
模式)。我建议重命名您的
Result
类型,因为有一个众所周知的通用名为Result<Success, Failure>
返回.success(Success)
或.failure(Failure)
。这是我们已经使用了一段时间的模式,但也在 Swift 5 中正式引入。请参阅SE-0235 .您的代码库可以有自己的
Result
类型,但如果您开始采用此Result<T, U>
,这会在以后引起困惑。约定。您确实不应该从
init
启动异步进程。 ,而是调用一个方法来执行此操作。就个人而言,我会将转换移至
UIImage
进入DataController
,例如extension DataController { func downloadImage(with url: URL, completion: @escaping (UIImage?, Error?) -> Void) { let task = URLSession.shared.dataTask(with: url) { data, _, error in let image = data.flatMap { UIImage(data: $0) } completion(image, error) } task.resume() } }
所以,我可能建议你最终得到这样的结果:
class SearchCollectionViewModel {
let name: String
let previewURL: String?
let dataController = DataController()
var image: UIImage?
init(with result: Result) {
self.name = result.trackName
self.previewURL = result.previewURL
}
}
extension SearchCollectionViewModel {
func preview(with url: String, completion: @escaping (UIImage?) -> Void) {
guard let urlString = previewURL, let url = URL(string: urlString) else {
completion(nil)
return
}
dataController.downloadImage(with: url) { [weak self] image, error in
DispatchQueue.main.async {
self?.image = image
completion(image)
}
}
}
}
关于swift - 不知道如何得到完成结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55784421/