简体   繁体   English

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

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

I'm trying to use an extension of UIImage to convert image download URLs to UIImage, but I'm getting this error: 'self.init' isn't called on all paths before returning from initializer我正在尝试使用 UIImage 的扩展名将图像下载 URL 转换为 UIImage,但出现此错误: 'self.init' isn't called on all paths before returning from initializer

Here is my whole extension:这是我的整个扩展:

( https://i.stack.imgur.com/oZGJu.png ) ( 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()
    }
}

I don't know what I'm missing or if I should try a new way to convert URL to UIImage. I tried a different way, but it throws an error saying I need to do it asynchronously.我不知道我错过了什么,或者我是否应该尝试一种将 URL 转换为 UIImage 的新方法。我尝试了一种不同的方法,但它抛出了一个错误,提示我需要异步进行。

A standard initializer cannot simply return an image that was fetched asynchronously.标准的初始化程序不能简单地返回异步获取的图像。

Assuming you are not using Swift concurrency with its async - await , you can write a static function with a completion handler closure which will asynchronously return the image:假设您没有使用 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
    }
}

And then call this static function with its completion handler, eg:然后用它的完成处理程序调用这个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
        }
    }
}

However, if you were using Swift concurrency with its async - await , you can write an async initializer:但是,如果您使用 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)
    }
}

And you can then use this from an asynchronous context, eg:然后您可以从异步上下文中使用它,例如:

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

You're missing a self.init call For convenience inits you'd write self.init and follow up with a standard init that's already defined Also you need to return nil where your init fails你错过了一个 self.init 调用 为了方便你编写 self.init 并跟进一个已经定义的标准 init 另外你需要在你的 init 失败的地方返回 nil

暂无
暂无

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

相关问题 在从初始化程序返回之前,不会在所有路径上调用“self.init” - 'self.init' isn't called on all paths before returning from initializer CoreData和Codable类编译器错误:从初始化程序返回之前,未在所有路径上调用&#39;self.init&#39; - CoreData and Codable class compiler error: 'self.init' isn't called on all paths before returning from initializer json.swift 错误是 Self.init 未在委托初始化程序的所有路径上调用 - json.swift error is Self.init isn't called on all paths in delegating initializer Swift:在从初始化程序返回之前没有在所有路径上调用“super.init”? - Swift: 'super.init' isn't called on all paths before returning from initializer? 在从初始化程序错误返回之前,不会在所有路径上调用Super.init - Super.init isn't called on all paths before returning from initializer Error 解决“从初始化快速返回之前未在所有路径上调用Super.init的问题”。 - Problems getting around 'Super.init isn't called on all paths before returning from initializer swift.' 从初始化程序返回之前,并非在所有路径上都调用“ super.init” - 'super.init' isn't called on all paths before returning from initializer 在从初始化程序返回之前,不会在所有路径上调用“super.init”。 但是没用 - 'super.init' isn't called on all paths before returning from initializer. But it's useless 在从初始化程序返回之前,不会在所有路径上调用super init - super init isn't called on all paths before returning from initializer 在调用self.init之前自己使用的iOS Swift便利初始化程序 - iOS Swift convenience initializer self used before self.init called
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM