Like iOS8 / OSX10.10, there is a built-in way to create zip archives using NSFileCoordinatorReadingOptions.ForUploading . A simple example of creating zip archives without dependencies is not Cocoa:
public extension NSURL { /// Creates a zip archive of the file/folder represented by this URL and returns a references to the zipped file /// /// - parameter dest: the destination URL; if nil, the destination will be this URL with ".zip" appended func zip(dest: NSURL? = nil) throws -> NSURL { let destURL = dest ?? self.URLByAppendingPathExtension("zip") let fm = NSFileManager.defaultManager() var isDir: ObjCBool = false let srcDir: NSURL let srcDirIsTemporary: Bool if let path = self.path where self.fileURL && fm.fileExistsAtPath(path, isDirectory: &isDir) && isDir.boolValue == true { // this URL is a directory: just zip it in-place srcDir = self srcDirIsTemporary = false } else { // otherwise we need to copy the simple file to a temporary directory in order for // NSFileCoordinatorReadingOptions.ForUploading to actually zip it up srcDir = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString) try fm.createDirectoryAtURL(srcDir, withIntermediateDirectories: true, attributes: nil) let tmpURL = srcDir.URLByAppendingPathComponent(self.lastPathComponent ?? "file") try fm.copyItemAtURL(self, toURL: tmpURL) srcDirIsTemporary = true } let coord = NSFileCoordinator() var error: NSError? // coordinateReadingItemAtURL is invoked synchronously, but the passed in zippedURL is only valid // for the duration of the block, so it needs to be copied out coord.coordinateReadingItemAtURL(srcDir, options: NSFileCoordinatorReadingOptions.ForUploading, error: &error) { (zippedURL: NSURL) -> Void in do { try fm.copyItemAtURL(zippedURL, toURL: destURL) } catch let err { error = err as NSError } } if srcDirIsTemporary { try fm.removeItemAtURL(srcDir) } if let error = error { throw error } return destURL } } public extension NSData { /// Creates a zip archive of this data via a temporary file and returns the zipped contents func zip() throws -> NSData { let tmpURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString) try self.writeToURL(tmpURL, options: NSDataWritingOptions.DataWritingAtomic) let zipURL = try tmpURL.zip() let fm = NSFileManager.defaultManager() let zippedData = try NSData(contentsOfURL: zipURL, options: NSDataReadingOptions()) try fm.removeItemAtURL(tmpURL) // clean up try fm.removeItemAtURL(zipURL) return zippedData } }
Marc prud'hommeaux
source share