diff --git a/Zip/QuickZip.swift b/Zip/QuickZip.swift index ebb2274c00aafce4498981d6a68bc2e4ebc18559..3cb1548e6af39fae823868b8a7649962ec91f67c 100644 --- a/Zip/QuickZip.swift +++ b/Zip/QuickZip.swift @@ -11,7 +11,7 @@ import Foundation extension Zip { //MARK: Quick Unzip - + /** Quick unzip a file. Unzips to a new folder inside the app's documents folder with the zip file's name. @@ -33,6 +33,8 @@ extension Zip { - throws: Error if unzipping fails or if file is not found. Can be printed with a description variable. + - notes: Supports implicit progress composition + - returns: NSURL of the destination folder. */ public class func quickUnzipFile(path: NSURL, progress: ((progress: Double) -> ())?) throws -> NSURL { @@ -50,30 +52,34 @@ extension Zip { //MARK: Quick Zip /** - Quick zip files. - - - parameter paths: Array of NSURL filepaths. - - parameter fileName: File name for the resulting zip file. - - - throws: Error if zipping fails. - - - returns: NSURL of the destination folder. - */ + Quick zip files. + + - parameter paths: Array of NSURL filepaths. + - parameter fileName: File name for the resulting zip file. + + - throws: Error if zipping fails. + + - notes: Supports implicit progress composition + + - returns: NSURL of the destination folder. + */ public class func quickZipFiles(paths: [NSURL], fileName: String) throws -> NSURL { return try quickZipFiles(paths, fileName: fileName, progress: nil) } - - /** - Quick zip files. - - - parameter paths: Array of NSURL filepaths. - - parameter fileName: File name for the resulting zip file. - - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. - - - throws: Error if zipping fails. - - returns: NSURL of the destination folder. - */ + /** + Quick zip files. + + - parameter paths: Array of NSURL filepaths. + - parameter fileName: File name for the resulting zip file. + - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. + + - throws: Error if zipping fails. + + - notes: Supports implicit progress composition + + - returns: NSURL of the destination folder. + */ public class func quickZipFiles(paths: [NSURL], fileName: String, progress: ((progress: Double) -> ())?) throws -> NSURL { let fileManager = NSFileManager.defaultManager() let documentsUrl = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL @@ -82,5 +88,5 @@ extension Zip { return destinationUrl } - + } \ No newline at end of file diff --git a/Zip/Zip.swift b/Zip/Zip.swift index 38a97adba89646cd56f0fcc1b20482b741ed3658..43d804a2aa7fba35f58d74466fa8c873b993c47e 100644 --- a/Zip/Zip.swift +++ b/Zip/Zip.swift @@ -17,7 +17,7 @@ public enum ZipError: ErrorType { case UnzipFail /// Zip fail case ZipFail - + /// User readable description public var description: String { switch self { @@ -42,7 +42,7 @@ public class Zip { } // MARK: Unzip - + /** Unzip file @@ -51,15 +51,17 @@ public class Zip { - parameter overwrite: Overwrite bool. - parameter password: Optional password if file is protected. - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. - + - throws: Error if unzipping fails or if fail is not found. Can be printed with a description variable. + + - notes: Supports implicit progress composition */ - + public class func unzipFile(zipFilePath: NSURL, destination: NSURL, overwrite: Bool, password: String?, progress: ((progress: Double) -> ())?) throws { // File manager let fileManager = NSFileManager.defaultManager() - + // Check whether a zip file exists at path. guard let path = zipFilePath.path where destination.path != nil else { throw ZipError.FileNotFound @@ -81,7 +83,12 @@ public class Zip { if let attributeFileSize = fileAttributes[NSFileSize] as? Double { totalSize += attributeFileSize } - + + let progressTracker = NSProgress(totalUnitCount: Int64(totalSize)) + progressTracker.cancellable = false + progressTracker.pausable = false + progressTracker.kind = NSProgressKindFile + // Begin unzipping let zip = unzOpen64(path) if unzGoToFirstFile(zip) != UNZ_OK { @@ -165,27 +172,33 @@ public class Zip { progressHandler(progress: (currentPosition/totalSize)) } + progressTracker.completedUnitCount = Int64(currentPosition) + } while (ret == UNZ_OK && ret != UNZ_END_OF_LIST_OF_FILE) // Completed. Update progress handler. if let progressHandler = progress{ progressHandler(progress: 1.0) } - + + progressTracker.completedUnitCount = Int64(totalSize) + } // MARK: Zip /** - Zip files. - - - parameter paths: Array of NSURL filepaths. - - parameter zipFilePath: Destination NSURL, should lead to a .zip filepath. - - parameter password: Password string. Optional. - - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. - - - throws: Error if zipping fails. - */ + Zip files. + + - parameter paths: Array of NSURL filepaths. + - parameter zipFilePath: Destination NSURL, should lead to a .zip filepath. + - parameter password: Password string. Optional. + - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. + + - throws: Error if zipping fails. + + - notes: Supports implicit progress composition + */ public class func zipFiles(paths: [NSURL], zipFilePath: NSURL, password: String?, progress: ((progress: Double) -> ())?) throws { // File manager @@ -218,6 +231,11 @@ public class Zip { catch {} } + let progressTracker = NSProgress(totalUnitCount: Int64(totalSize)) + progressTracker.cancellable = false + progressTracker.pausable = false + progressTracker.kind = NSProgressKindFile + // Begin Zipping let zip = zipOpen(destinationPath, APPEND_STATUS_CREATE) for path in processedPaths { @@ -268,6 +286,8 @@ public class Zip { progressHandler(progress: (currentPosition/totalSize)) } + progressTracker.completedUnitCount = Int64(currentPosition) + zipCloseFileInZip(zip) free(buffer) fclose(input) @@ -279,8 +299,10 @@ public class Zip { if let progressHandler = progress{ progressHandler(progress: 1.0) } + + progressTracker.completedUnitCount = Int64(totalSize) } - + } \ No newline at end of file diff --git a/ZipTests/ZipTests.swift b/ZipTests/ZipTests.swift index 53fe334f054bcdb0d894bd427afc0550c2152234..f80b6e4d47577d7546a43d6523930524a0b9ab85 100644 --- a/ZipTests/ZipTests.swift +++ b/ZipTests/ZipTests.swift @@ -43,7 +43,7 @@ class ZipTests: XCTestCase { XCTAssert(true) } } - + func testQuickUnzipNonZipPath() { do { let filePath = NSBundle(forClass: ZipTests.self).URLForResource("3crBXeO", withExtension: "gif")! @@ -84,9 +84,11 @@ class ZipTests: XCTestCase { do { let filePath = NSBundle(forClass: ZipTests.self).URLForResource("bb8", withExtension: "zip")! let documentsFolder = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL + try Zip.unzipFile(filePath, destination: documentsFolder, overwrite: true, password: "password", progress: { (progress) -> () in print(progress) }) + let fileManager = NSFileManager.defaultManager() XCTAssertTrue(fileManager.fileExistsAtPath(documentsFolder.path!)) } @@ -95,6 +97,48 @@ class ZipTests: XCTestCase { } } + func testImplicitProgressUnzip() { + do { + let progress = NSProgress() + progress.totalUnitCount = 1 + + let filePath = NSBundle(forClass: ZipTests.self).URLForResource("bb8", withExtension: "zip")! + let documentsFolder = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL + + progress.becomeCurrentWithPendingUnitCount(1) + try Zip.unzipFile(filePath, destination: documentsFolder, overwrite: true, password: "password", progress: nil) + progress.resignCurrent() + + XCTAssertTrue(progress.totalUnitCount == progress.completedUnitCount) + } + catch { + XCTFail() + } + + } + + func testImplicitProgressZip() { + do { + let progress = NSProgress() + progress.totalUnitCount = 1 + + let imageURL1 = NSBundle(forClass: ZipTests.self).URLForResource("3crBXeO", withExtension: "gif")! + let imageURL2 = NSBundle(forClass: ZipTests.self).URLForResource("kYkLkPf", withExtension: "gif")! + let documentsFolder = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL + let zipFilePath = documentsFolder.URLByAppendingPathComponent("archive.zip") + + progress.becomeCurrentWithPendingUnitCount(1) + try Zip.zipFiles([imageURL1, imageURL2], zipFilePath: zipFilePath, password: nil, progress: nil) + progress.resignCurrent() + + XCTAssertTrue(progress.totalUnitCount == progress.completedUnitCount) + } + catch { + XCTFail() + } + } + + func testQuickZip() { do { let imageURL1 = NSBundle(forClass: ZipTests.self).URLForResource("3crBXeO", withExtension: "gif")! @@ -129,7 +173,7 @@ class ZipTests: XCTestCase { XCTFail() } } - + func testZip() { do { @@ -164,6 +208,6 @@ class ZipTests: XCTestCase { XCTFail() } } - - + + }