是否有可能在不快速调用 API 的情况下从互联网获取图像?

Posted

技术标签:

【中文标题】是否有可能在不快速调用 API 的情况下从互联网获取图像?【英文标题】:Is there a possibility to get the image from internet without calling API in swift? 【发布时间】:2021-11-04 02:17:01 【问题描述】:

从第一次调用 api强>。并且必须从嵌套在 json 对象中的链接中获取图像(从获得的数据中解析)。我是否需要创建一个单独的方法,该方法将再次使用 json 的嵌套链接调用 api 或者是否有任何速记(框架工作)方法可以做到这一点。喜欢,

let image = UIImage(data: imageData) // 框架中的默认方法 let image = UIImage(contentsOfFile : fileLocation) // 框架中的默认方法

let image = UIImage(url: URL) // 期待这样的方法

我期待一种类似上述的方法,它可以直接从 url 获取图像,而无需重复调用 api 从嵌套链接中获取图像。有没有可能,这样我就可以避免多次api调用并最小化线程?

【问题讨论】:

将 URL 保存在内存中,在该特定图像数据上再次使用 URLSession,然后对其调用 UIImage(data: imageData)。或者使用 SDWebImage、Alamofire+Image、KingFisher... avoid multiple api calls and minimise threads - 使用推荐的方法时,您是否发现线程数有问题? 【参考方案1】:

自从引入 Combine 框架以来,嵌套网络调用变得非常舒适。

这是jsonplaceholder API 的示例。代码首先加载包含 idurl 的 JSON,然后在此 URL 加载图像

import Combine

struct Photo : Decodable, Identifiable 
    let id : Int
    let url : URL


var storage : AnyCancellable?

let baseURL = URL(string: "https://jsonplaceholder.typicode.com/photos/1")!
storage = URLSession.shared.dataTaskPublisher(for: baseURL)
    .map(\.data)
    .decode(type: Photo.self, decoder: JSONDecoder())
    .map(\.url)
    .flatMap  url in
        URLSession.shared.dataTaskPublisher(for: url)
            .map(\.data)
            .replaceError(with: Data())
            .eraseToAnyPublisher()
    
    .receive(on: DispatchQueue.main)
    .sink  result in
        print(result)
     receiveValue:  imageData in
        print("Image successfully loaded containing", imageData)
        let image = UIImage(data: imageData)
    

【讨论】:

【参考方案2】:

您也可以在不调用 api 的情况下显示来自 url 的图像。要实现这一点,您需要将 url 转换为 Data

let imageURL = "https://picsum.photos/200/300"
let imageData = Data(contentsOf: URL(string: imageURL)!)
let finalImage = UIImage(data: imageData)




 extension UIImageView 
        func load(imageURL: URL) 
            DispatchQueue.global().async  [weak self] in
               let imageData = Data(contentsOf: imageURL)
               let finalImage = UIImage(data: imageData)
              DispatchQueue.main.async 
                       //set your image here in main thread 
               
            
        
    

请尝试一下,看看它是否适合你

【讨论】:

强烈建议您不要与Data(contentsOf:) 同步加载数据。别。它阻塞线程并导致糟糕的用户体验。 是的,我同意,我不欣赏这种方法,但根据问题,我只想表明这是可以实现的 我已经更新了我的答案,请您建议这种方法可以同步加载图像吗? 它仍然阻塞线程,不是主线程而是公共全局线程。使用 URLSession 异步加载数据——无论是使用传统的完成处理程序还是使用现代的组合发布者——是最先进的。 严格来说,URLSessionData(contentsOf 都执行一种 API 调用。使用 Combine,您可以以一种同步的外观但异步的性能链接多个调用。

以上是关于是否有可能在不快速调用 API 的情况下从互联网获取图像?的主要内容,如果未能解决你的问题,请参考以下文章

在不打开应用程序的情况下从 Firebase 更新应用程序数据

如何在不知道匹配返回的 json 数据中的所有值的情况下从 .Net 核心中的 Web api 调用创建模型?

如何在不使用 curl 和 guzzle 的情况下从控制器 Laravel 调用 API,因为它不起作用 [关闭]

如何在不传递委托的情况下从 RootViewController 调用 AppDelegate 方法?

我可以在不显式调用 headObject 的情况下从 S3 对象流中获取 Content-Type 吗?

如何在不使用 ImageView 的情况下从 API 端点下载图像或位图?