You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Kingfisher获取网络图片后存入数组复用的实现求助

没问题,我帮你调整代码实现预加载图片到数组再轮播的需求,这样就能彻底避免重复网络请求了。下面是具体的实现思路和代码示例:

实现思路
  • 先定义存储图片的数组、当前展示索引和定时器变量
  • 批量预加载所有目标图片URL对应的UIImage,存入数组(用Kingfisher的ImageDownloader来获取图片数据)
  • 所有图片加载完成后,启动定时器,每隔5秒从数组中取对应图片展示到ImageView
  • 处理边界情况(比如数组为空、索引越界、下载失败的图片)
完整代码示例
import UIKit
import Kingfisher

class ImageCarouselVC: UIViewController {
    // 你的展示ImageView
    @IBOutlet weak var displayImageView: UIImageView!
    
    // 存储预加载好的图片
    private var preloadedImages: [UIImage] = []
    // 当前展示的图片索引
    private var currentImageIndex = 0
    // 轮播定时器
    private var carouselTimer: Timer?
    // 替换成你的所有目标图片URL数组
    private let imageURLs: [URL] = [
        URL(string: "https://example.com/image1.jpg")!,
        URL(string: "https://example.com/image2.jpg")!,
        URL(string: "https://example.com/image3.jpg")!
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 启动图片预加载流程
        preloadAllImages()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // 页面消失时销毁定时器,避免内存泄漏
        carouselTimer?.invalidate()
        carouselTimer = nil
    }
    
    private func preloadAllImages() {
        let dispatchGroup = DispatchGroup()
        
        for url in imageURLs {
            dispatchGroup.enter()
            // 使用Kingfisher的ImageDownloader下载图片,拿到UIImage对象
            ImageDownloader.shared.downloadImage(with: url) { [weak self] result in
                defer {
                    dispatchGroup.leave()
                }
                switch result {
                case .success(let value):
                    // 下载成功,将图片加入数组(确保在主线程更新UI相关数组)
                    DispatchQueue.main.async {
                        self?.preloadedImages.append(value.image)
                    }
                case .failure(let error):
                    // 处理下载失败的情况,比如添加占位图或者跳过
                    print("下载图片失败: \(error.localizedDescription)")
                    DispatchQueue.main.async {
                        self?.preloadedImages.append(UIImage(named: "placeholder")!)
                    }
                }
            }
        }
        
        // 所有图片下载完成后启动轮播
        dispatchGroup.notify(queue: .main) { [weak self] in
            guard let self = self, !self.preloadedImages.isEmpty else {
                print("没有可用图片,无法启动轮播")
                return
            }
            // 先展示第一张图片
            self.displayImageView.image = self.preloadedImages[self.currentImageIndex]
            // 启动定时器,每5秒切换一次
            self.startCarouselTimer()
        }
    }
    
    private func startCarouselTimer() {
        carouselTimer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { [weak self] _ in
            guard let self = self else { return }
            // 更新索引,取模运算避免越界
            self.currentImageIndex = (self.currentImageIndex + 1) % self.preloadedImages.count
            // 从数组取图片直接展示
            self.displayImageView.image = self.preloadedImages[self.currentImageIndex]
        }
    }
}
关键细节说明
  • 预加载方式:用ImageDownloader.shared.downloadImage而不是直接用kf.setImage,因为我们需要拿到UIImage对象存入数组,而不是直接设置到ImageView
  • 异步处理:用DispatchGroup来等待所有图片下载完成,确保轮播开始时数组已经有内容
  • 线程安全:所有更新UI和数组的操作都放在主线程,避免多线程冲突
  • 内存管理:在viewWillDisappear中销毁定时器,并用weak self避免循环引用
  • 边界处理:检查数组是否为空,用取模运算处理索引越界,同时处理下载失败的情况(比如添加占位图)

内容的提问来源于stack exchange,提问作者user7477041

火山引擎 最新活动