![](/img/trans.png)
[英]'self.init' isn't called on all paths before returning from initializer
[英]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.