[英]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.