Search code examples
swiftzipfoundation

How to print progress with ZIPFoundation


How can I track and print progress percentage to console on each progress update using ZIPFoundation in a class file that is not a controller?

I am quite new to swift and I have been trying to understand how Progress works for quite a long time because it seems like it can be used to track the progress of unzip process using ZIPFoundation module (unfortunately without a luck so far). For the info, the unzipping itself works fine for me.

As far as I know it should be something similar to this, but I am not sure how to track it:

class MyClass {
    @objc var unzipProgress: Progress?

func unzipFile(from: URL, to: URL) -> Bool {
        let fileManager = FileManager()
        
        print("Unzipping...")
        do {            
            // How to track unzipProgress?
            try fileManager.unzipItem(at: from, to: to, progress: unzipProgress)
            print("Extraction success from \(from.path) to \(to.path)")
        } catch {
            print("Extraction of ZIP archive failed with error:\(error)")
        }
    }

Edit: I am familiar with this post but it does not help me as it uses JGProgressHUD and a controller class.


Solution

  • The documentation for ZIPFoundation tells you how to monitor progress.

    You need to create a Progress object:

    let unzipProgress = Progress()
    

    Then you need to setup an observer for the fractionCompleted property:

    let observation = unzipProgress.observe(\.fractionCompleted) { progress, _ in
      print("progress: ", progress.fractionCompleted)
    }
    

    Then pass in your unzipProgress to one of the zip methods:

    try fileManager.unzipItem(at: from, to: to, progress: unzipProgress)
    

    Then you can cleanup the observation:

    observation.invalidate()
    

    Your unzipFile function becomes something like this:

    func unzipFile(from: URL, to: URL) -> Bool {
        let fileManager = FileManager()
    
        let unzipProgress = Progress()
        let observation = unzipProgress.observe(\.fractionCompleted) { progress, _ in
           print("Extraction progress: ", progress.fractionCompleted)
        }
        
        print("Unzipping...")
        do {            
            // How to track unzipProgress?
            try fileManager.unzipItem(at: from, to: to, progress: unzipProgress)
            print("Extraction success from \(from.path) to \(to.path)")
        } catch {
            print("Extraction of ZIP archive failed with error:\(error)")
        }
    
        observation.invalidate()
    }
    

    You can remove your unzipProgress property from your class since you only need the local variable.