You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS条码扫描App异步调用getThumb API并更新UI的实现方案

解决方案:异步加载图片并主线程更新UI

你的问题核心是setImageFromURl方法使用了同步的NSData(contentsOf:),这个方法会阻塞调用线程——由于你在主线程的异步闭包里调用它,直接导致主线程被卡住,触发Xcode的UI无响应警告。

只需要把同步加载图片的逻辑改成基于URLSession的异步实现,同时确保UI更新操作在主线程执行即可解决问题:

修改后的UIImageView扩展

extension UIImageView {
    func setImageFromURL(stringImageUrl urlString: String) {
        // 可选:先清空旧图片或设置占位图
        self.image = nil
        
        guard let url = URL(string: urlString) else {
            print("无效的图片URL")
            return
        }
        
        URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let self = self, let imageData = data, error == nil else {
                print("图片加载失败:\(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            // 必须在主线程更新UI
            DispatchQueue.main.async {
                self.image = UIImage(data: imageData)
            }
        }.resume()
    }
}

额外优化:避免重复请求(可选)

如果你的App存在快速切换图片的场景(比如列表滚动),可以给UIImageView添加任务管理逻辑,取消未完成的旧请求,防止旧图片覆盖新图片:

extension UIImageView {
    // 用关联对象存储当前加载任务
    private static var taskAssociationKey = 0
    private var currentLoadTask: URLSessionDataTask? {
        get { objc_getAssociatedObject(self, &Self.taskAssociationKey) as? URLSessionDataTask }
        set { objc_setAssociatedObject(self, &Self.taskAssociationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
    }
    
    func setImageFromURL(stringImageUrl urlString: String, placeholder: UIImage? = nil) {
        // 取消之前未完成的请求
        currentLoadTask?.cancel()
        // 设置占位图
        self.image = placeholder
        
        guard let url = URL(string: urlString) else {
            print("无效的图片URL")
            return
        }
        
        let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let self = self else { return }
            
            // 排除任务被取消的情况
            if let error = error, (error as NSError).code == URLError.cancelled.rawValue {
                print("图片加载已取消")
                return
            }
            
            guard let imageData = data, error == nil else {
                print("图片加载失败:\(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            DispatchQueue.main.async {
                self.image = UIImage(data: imageData)
            }
        }
        currentLoadTask = task
        task.resume()
    }
}

原代码调用无需修改

原来downLoadJson方法中调用self.imageVW.setImageFromURL(...)的代码保持不变即可,因为现在这个方法已经是异步执行,不会阻塞主线程。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:31:10