不知道如何获得完成的结果

时间:2019-04-21 16:12:48

标签: swift completion

我无法使用完成处理程序的结果。 我收到此错误“无法将类型'()'的值转换为预期的参数类型”

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)
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

一些观察结果:

  1. 您不能“返回”通过转义闭包异步检索的值。

  2. 闭包定义(Data) -> Data?表示闭包不仅将传递为图像检索的Data,而且闭包本身将返回一些信息到{{1} }。但这显然不是这样做的(因此需要preview,如_一样)。我建议您将其更改为_ = completion(...)(或使用(Data?) -> Void模式)。

  3. 我建议重命名您的Result<T, U>类型,因为有一个众所周知的泛型Result用于返回Result<Success, Failure>.success(Success)。这是我们使用了一段时间的一种模式,但是Swift 5也正式引入了这种模式。参见SE-0235

    您的代码库可以有自己的.failure(Failure)类型,但是如果您开始采用此Result约定,这会在以后引起混乱。

  4. 您实际上不应该从Result<T, U>启动异步过程,而应该调用一种方法来实现。

  5. 我个人将转换为initUIImage中,例如

    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()
    }
}