Swift 4中如何在压缩文件时显示JGProgressHUD进度提示?
解决Zip框架进度回调中JGProgressHUD延迟显示的问题
嗨,这个问题我做文件压缩功能时也踩过一模一样的坑!核心原因其实很好理解:所有UI相关操作必须在主线程执行,而marmelroy/Zip框架的进度回调闭包是在后台线程触发的,这就导致HUD的更新被系统延迟处理,直到压缩操作完成、主线程空闲后才一次性显示出来。
问题根源拆解
Zip框架为了避免阻塞主线程(防止界面卡死),会把压缩/解压这类耗时操作放到后台队列执行,对应的进度回调闭包自然也运行在后台线程里。而JGProgressHUD是UI控件,iOS系统明确规定:所有UI的创建、更新、显示操作都必须在主线程完成,后台线程的UI操作会被系统暂存,直到主线程有空才会处理——这就是你看到HUD只在结束后才显示的直接原因。
具体解决代码
只需要把进度闭包和完成回调里的HUD操作,用DispatchQueue.main.async包裹起来,强制切换到主线程执行即可:
func quickZipFiles() { // 初始化并显示HUD(确保在主线程执行,这里如果是在ViewController方法里调用,默认就是主线程) let hud = JGProgressHUD(style: .dark) hud.textLabel.text = "正在压缩..." hud.show(in: self.view) let filePaths = ["path/to/target/file1", "path/to/target/file2"] let zipOutputPath = "path/to/save/zip/file.zip" Zip.zipFiles(paths: filePaths, zipFilePath: zipOutputPath, progress: { progress in // 把进度更新操作切回主线程 DispatchQueue.main.async { hud.progress = progress } }) { success, error in // 完成回调里的HUD收尾操作同样要切主线程 DispatchQueue.main.async { if let error = error { hud.textLabel.text = "压缩失败:\(error.localizedDescription)" hud.dismiss(afterDelay: 2) } else { hud.textLabel.text = "压缩完成" hud.dismiss(afterDelay: 1) } } } }
额外注意事项
- 你在
viewDidLoad里调用HUD正常,是因为viewDidLoad本身就在主线程执行,所以UI操作不受限制。 - 不仅是进度更新,HUD的
show、dismiss、文字修改等所有操作,只要是在后台线程触发的回调里,都必须包裹到DispatchQueue.main.async中。 - 别尝试把压缩操作挪到主线程执行,那样会导致界面完全卡死,Zip框架的后台处理设计是合理的,我们只需要把UI操作切回主线程就好。
内容的提问来源于stack exchange,提问作者Salva
相关产品推荐
相关产品推荐

