Working with ZIP/archives in Swift (iOS/macOS)
In modern iOS and macOS development, there is often a need to package and unpackage files. ZIP archives are a standard data compression method supported on all Apple platforms. In this article, we will look at native Swift tools for working with ZIP, as well as the popular library ZIPFoundation.
Native Foundation tools
The Foundation framework provides basic capabilities for working with archives through the NSFileCoordinator class and system utilities. However, for full-fledged work with ZIP, it is recommended to use third-party libraries or wrappers over system commands.
ZIPFoundation library
ZIPFoundation is a lightweight library for working with ZIP archives, written in pure Swift. It supports iOS, macOS, tvOS, and watchOS, requires no external dependencies, and is distributed under the MIT license.
Installation via Swift Package Manager
Add the dependency to Package.swift:
dependencies: [ .package(url: "https://github.com/weichsel/ZIPFoundation.git", from: "0.9.16")]Or via Xcode: File → Add Packages → enter the repository URL.
Basic operations
1. Creating a ZIP archive
Packaging a single file:
import ZIPFoundation
let fileManager = FileManager.defaultlet sourceURL = URL(fileURLWithPath: "/path/to/file.txt")let destinationURL = URL(fileURLWithPath: "/path/to/archive.zip")
do { try fileManager.zipItem(at: sourceURL, to: destinationURL) print("Archive created: \\(destinationURL.path)")} catch { print("Error: \\(error.localizedDescription)")}Packaging an entire directory:
let directoryURL = URL(fileURLWithPath: "/path/to/folder")let archiveURL = URL(fileURLWithPath: "/path/to/folder.zip")
do { try fileManager.zipItem(at: directoryURL, to: archiveURL) print("Directory packaged")} catch { print("Error: \\(error)")}2. Extracting an archive
let archiveURL = URL(fileURLWithPath: "/path/to/archive.zip")let destinationURL = URL(fileURLWithPath: "/path/to/unzip")
do { try fileManager.unzipItem(at: archiveURL, to: destinationURL) print("Extraction complete")} catch { print("Extraction error: \\(error)")}3. Working with archive contents without extraction
guard let archive = Archive(url: archiveURL, accessMode: .read) else { fatalError("Failed to open archive")}
// List all entriesfor entry in archive { print("File: \\(entry.path), size: \\(entry.uncompressedSize) bytes")}
// Reading a specific fileif let entry = archive["documents/report.pdf"] { var data = Data() do { _ = try archive.extract(entry, bufferSize: 4096) { partialData in data.append(partialData) } print("Extracted \\(data.count) bytes") } catch { print("Error: \\(error)") }}4. Adding files to an existing archive
guard let archive = Archive(url: archiveURL, accessMode: .update) else { fatalError("Failed to open archive for update")}
let newFileURL = URL(fileURLWithPath: "/path/to/new_file.txt")do { try archive.addEntry(with: "new_file.txt", relativeTo: newFileURL.deletingLastPathComponent()) print("File added")} catch { print("Error: \\(error)")}Working with progress and large files
For large archives, use Progress:
let progress = Progress(totalUnitCount: 100)let archiveURL = URL(fileURLWithPath: "/path/to/large.zip")let destinationURL = URL(fileURLWithPath: "/path/to/output")
do { try FileManager.default.unzipItem(at: archiveURL, to: destinationURL, progress Also in library
Sending Email in Swift: Complete Guide to SMTP and MailKit
Laravel Framework for PHP: Complete Guide with Examples
Express.js for JavaScript (Node.js): Complete Guide with Examples
Authorization and Authentication in PHP: A Complete Guide with Examples
Caching in TypeScript: Redis and Other Solutions for Node.js