【问题标题】:How to show progress hud while compressing a file in Swift 4?如何在 Swift 4 中压缩文件时显示进度 hud?
【发布时间】:2018-08-04 23:46:57
【问题描述】:

我正在使用marmelroy/Zip framework 来压缩/解压缩项目中的文件,并使用JGProgressHUD 来显示操作的进度。

如果我尝试从 ViewDidLoad 方法显示它,我能够看到 HUD,但如果我在与 quickZipFiles 方法的进度功能相关的闭包中使用它(如代码示例中),则 hud 是在操作结束时显示。

我猜这可能与时间问题有关,但由于我对完成处理程序、闭包和 GDC(线程、异步任务等)不太感兴趣,所以我想请教一个建议。

有什么想法吗?

// In my class properties declaration
var hud = JGProgressHUD(style: .dark)

// In my ViewDidLoad
self.hud.indicatorView = JGProgressHUDPieIndicatorView()
self.hud.backgroundColor = UIColor(white: 0, alpha: 0.7)

// In my method
do {
    self.hud.textLabel.text = NSLocalizedString("Zipping files...", comment: "Zipping File Message")
    self.hud.detailTextLabel.text = "0%"
    if !(self.hud.isVisible) {
        self.hud.show(in: self.view)
    }
    zipURL = try Zip.quickZipFiles(documentsList, fileName: "documents", progress: { (progress) -> () in
        let progressMessage = "\(round(progress*100))%"
        print(progressMessage)
        self.hud.setProgress(Float(progress), animated: true)
        self.hud.textLabel.text = NSLocalizedString("Zipping files...", comment: "Zipping File Message")
        self.hud.detailTextLabel.text = progressMessage
        if (progress == 1.0) {
            self.hud.dismiss()
        }
    })
} catch {
    print("Error while creating zip...")
}

【问题讨论】:

    标签: swift zip progress-bar swift4 hud


    【解决方案1】:

    ZIP Foundation 内置了对进度报告和取消的支持。
    因此,如果您可以切换 ZIP 库,这可能更适合您的项目。 (完全披露:我是这个库的作者)

    这里有一些示例代码,展示了如何压缩目录并在JGProgressHUD 上显示操作进度。我只是在这里压缩主包的目录作为示例。

    ZIP 操作在单独的线程上调度,以便您的主线程可以更新 UI。 progress var 是默认的 Foundation (NS)Progress 对象,它通过 KVO 报告更改。

    import UIKit
    import ZIPFoundation
    import JGProgressHUD
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var progressLabel: UILabel!
        var indicator = JGProgressHUD()
        var isObservingProgress = false
        var progressViewKVOContext = 0
    
        @objc
        var progress: Progress?
    
        func startObservingProgress()
        {
            guard !isObservingProgress else { return }
    
            progress = Progress()
            progress?.completedUnitCount = 0
            self.indicator.progress = 0.0
    
            self.addObserver(self, forKeyPath: #keyPath(progress.fractionCompleted), options: [.new], context: &progressViewKVOContext)
            isObservingProgress = true
        }
    
        func stopObservingProgress()
        {
            guard isObservingProgress else { return }
    
            self.removeObserver(self, forKeyPath: #keyPath(progress.fractionCompleted))
            isObservingProgress = false
            self.progress = nil
        }
    
        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
            if keyPath == #keyPath(progress.fractionCompleted) {
                DispatchQueue.main.async {
                    self.indicator.progress = Float(self.progress?.fractionCompleted ?? 0.0)
                    if let progressDescription = self.progress?.localizedDescription {
                        self.progressLabel.text = progressDescription
                    }
    
                    if self.progress?.isFinished == true {
                        self.progressLabel.text = ""
                        self.indicator.progress = 0.0
                    }
                }
            } else {
                super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            }
        }
    
        @IBAction func cancel(_ sender: Any) {
            self.progress?.cancel()
        }
    
        @IBAction func createFullArchive(_ sender: Any) {
            let directoryURL = Bundle.main.bundleURL
    
            let tempArchiveURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString).appendingPathExtension("zip")
            self.startObservingProgress()
            DispatchQueue.global().async {
                try? FileManager.default.zipItem(at: directoryURL, to: tempArchiveURL, progress: self.progress)
                self.stopObservingProgress()
            }
        }
    }
    

    【讨论】:

    • 非常感谢 Thomas,我一定会尽快调查的。
    【解决方案2】:

    查看 zip 库的实现,所有的压缩/解压缩以及对进度处理程序的调用都在同一个线程上完成。主页上显示的示例不是很好,如果您希望在压缩或解压缩时使用进度指示器更新 UI,则不能按原样使用。

    解决方案是在后台执行压缩/解压缩,在进度块中,更新主队列上的 UI。

    假设您正在从主队列调用您发布的代码(以响应用户执行某些操作),您应该按如下方式更新您的代码:

    // In my class properties declaration
    var hud = JGProgressHUD(style: .dark)
    
    // In my ViewDidLoad
    self.hud.indicatorView = JGProgressHUDPieIndicatorView()
    self.hud.backgroundColor = UIColor(white: 0, alpha: 0.7)
    
    self.hud.textLabel.text = NSLocalizedString("Zipping files...", comment: "Zipping File Message")
    self.hud.detailTextLabel.text = "0%"
    if !(self.hud.isVisible) {
        self.hud.show(in: self.view)
    }
    
    DispatchQueue.global().async {
        defer {
            DispatchQueue.main.async {
                self.hud.dismiss()
            }
        }
    
        do {
            zipURL = try Zip.quickZipFiles(documentsList, fileName: "documents", progress: { (progress) -> () in
                DispatchQueue.main.async {
                    let progressMessage = "\(round(progress*100))%"
                    print(progressMessage)
                    self.hud.setProgress(Float(progress), animated: true)
                    self.hud.textLabel.text = NSLocalizedString("Zipping files...", comment: "Zipping File Message")
                    self.hud.detailTextLabel.text = progressMessage
                }
            })
        } catch {
            print("Error while creating zip...")
        }
    }
    

    【讨论】:

    • 哇!你救了我一天!!奇迹般有效。非常感谢。由于我没有看到中止压缩操作的本机方法(但 HUD 允许某种交互),你知道我如何处理压缩线程的中止吗?
    • zip库的API不支持任何方式取消。
    • 不。我想知道我是否可以以某种方式强制它,也许取消线程或类似的东西。
    • 无法停止压缩,但您可以修改代码以停止更新进度视图并在用户选择取消时将其关闭。当您让用户继续使用应用程序时,zip 将在后台自行完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 2013-05-31
    • 2013-12-27
    • 2018-07-12
    • 1970-01-01
    相关资源
    最近更新 更多