Swift:在从 UIImage 扩展上的初始值设定项错误返回之前,不会在所有路径上调用'self.init'



我试图使用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函数与一个完成处理程序闭包,将异步返回图像:

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函数,例如:

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

你少了一个自我。init调用为了方便起见,你可以写self。Init,然后使用一个已经定义的标准Init你还需要在init失败的地方返回nil

相关内容

最新更新