swift - 不知道如何得到完成结果

标签 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. 您无法“返回”通过转义闭包异步检索的值。

  2. 闭包定义(Data) -> Data?表示关闭不仅会通过Data检索图像,但闭包本身会将某些内容返回到 preview 。但它显然没有这样做(因此需要 _ ,如 _ = completion(...) )。我建议您将其更改为 (Data?) -> Void (或使用 Result<T, U> 模式)。

  3. 我建议重命名您的 Result类型,因为有一个众所周知的通用名为 Result<Success, Failure>返回.success(Success).failure(Failure) 。这是我们已经使用了一段时间的模式,但也在 Swift 5 中正式引入。请参阅SE-0235 .

    您的代码库可以有自己的 Result类型,但如果您开始采用此 Result<T, U> ,这会在以后引起困惑。约定。

  4. 您确实不应该从 init 启动异步进程。 ,而是调用一个方法来执行此操作。

  5. 就个人而言,我会将转换移至 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/

相关文章:

执行自动尺寸时 IOS Swift TableView 边框问题

ios - 更改变量中的一个属性会触发对其他属性的订阅。接收 swift

arrays - 如何通过与swift中的另一个元素数组进行比较来从元素数组生成随机字符串?

ios - 将数据保存在钥匙串(keychain)中,只能通过 Swift 3 中的 Touch ID 访问

ios - 将标记 infoWindow 添加到 Mapbox 注释

Bash 完成使 'cd' 命令从其他正在运行的 shell 完成工作目录?

Elasticsearch 完成建议使用多词输入进行搜索

tabs - 是否可以在 elm repl 中完成制表符?

ios - 了解 UIView.animate 以及完成闭包的工作原理

emacs - 如何通过完成读取返回值而不是键