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
相关产品推荐
相关产品推荐

