繁体   English   中英

Swift:在从 UIImage 扩展的初始化错误返回之前,没有在所有路径上调用“self.init”

[英]Swift: 'self.init' isn't called on all paths before returning from initializer error on UIImage extension

我正在尝试使用 UIImage 的扩展名将图像下载 URL 转换为 UIImage,但出现此错误: 'self.init' isn't called on all paths before returning from initializer

这是我的整个扩展:

( https://i.stack.imgur.com/oZGJu.png )

extension UIImage {
    convenience init?(url: URL?) {
        let session = URLSession(configuration: .default)
        let downloadPicTask = session.dataTask(with: url!) { (data, response, error) in
            if let e = error {
                print("Error downloading picture: \(e)")
            } else {
                if let res = response as? HTTPURLResponse {
                    print("Downloaded picture with response code \(res.statusCode)")
                    if let imageData = data {
                        let image = UIImage(data: imageData)
                    } else {
                        print("Couldn't get image: Image is nil")
                    }
                } else {
                    print("Couldn't get response code for some reason")
                }
            }
        }
        downloadPicTask.resume()
    }
}

我不知道我错过了什么,或者我是否应该尝试一种将 URL 转换为 UIImage 的新方法。我尝试了一种不同的方法,但它抛出了一个错误,提示我需要异步进行。

标准的初始化程序不能简单地返回异步获取的图像。

假设您没有使用 Swift 并发及其async - await ,您可以编写一个static function 完成处理程序闭包,它将异步返回图像:

extension UIImage {
    enum ImageError: Error {
        case notImage
        case unknownError
    }

    @discardableResult
    static func fetchImage(from url: URL, queue: DispatchQueue = .main, completion: @escaping (Result<UIImage, Error>) -> Void) -> URLSessionDataTask? {
        let session = URLSession.shared
        let task = session.dataTask(with: url) { data, response, error in
            guard
                let data = data,
                error == nil,
                let response = response as? HTTPURLResponse
            else {
                queue.async { completion(.failure(error ?? ImageError.unknownError)) }
                return
            }

            print("Downloaded picture with response code \(response.statusCode)")

            guard let image = UIImage(data: data) else {
                queue.async { completion(.failure(ImageError.notImage)) }
                return
            }

            queue.async { completion(.success(image)) }
        }
        task.resume()

        return task
    }
}

然后用它的完成处理程序调用这个static function,例如:

func updateImageView() {
    let url = ...

    UIImage.fetchImage(from: url) { [weak self] result in
        switch result {
        case .failure(let error): print(error)
        case .success(let image): self?.imageView.image = image
        }
    }
}

但是,如果您使用 Swift 并发及其async - await则可以编写一个async初始化程序:

extension UIImage {
    convenience init?(from url: URL) async throws {
        let (data, _) = try await URLSession.shared.data(from: url)
        self.init(data: data)
    }
}

然后您可以从异步上下文中使用它,例如:

func updateImageView() async throws {
    let url = ...
    imageView.image = try await UIImage(from: url)
}

你错过了一个 self.init 调用 为了方便你编写 self.init 并跟进一个已经定义的标准 init 另外你需要在你的 init 失败的地方返回 nil

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM