Trabajo con archivos ZIP en Swift (iOS/macOS)
En el desarrollo moderno para iOS y macOS, a menudo surge la necesidad de comprimir archivos en archivos ZIP o extraer datos de ellos. Esto puede ser necesario para ahorrar espacio, transferir datos a través de la red u organizar copias de seguridad. En este artículo, veremos dos enfoques principales: el uso de las capacidades integradas de Foundation y la popular biblioteca de terceros ZipFoundation.
Herramientas integradas de Foundation (NSFileCoordinator + trabajo de bajo nivel)
Apple no proporciona una API de alto nivel para trabajar con ZIP en Foundation. Sin embargo, a partir de iOS 12 / macOS 10.14, existe la posibilidad de usar NSFileCoordinator y NSFileWrapper para algunas operaciones. Pero para un trabajo completo con ZIP, a menudo se utiliza la utilidad del sistema libz a través de la interfaz C.
Ejemplo: compresión de datos con libz
import Compressionimport Foundation
func compressData(_ data: Data) -> Data? { let sourceData = data as NSData let compressedData = NSMutableData(length: data.count)! var compressedSize = data.count let result = compression_encode( compressedData.mutableBytes.assumingMemoryBound(to: UInt8.self), &compressedSize, sourceData.bytes.assumingMemoryBound(to: UInt8.self), data.count, nil, COMPRESSION_ZLIB ) guard result == COMPRESSION_STATUS_OK else { return nil } compressedData.length = compressedSize return compressedData as Data}Biblioteca ZipFoundation (método recomendado)
ZipFoundation es una biblioteca ligera de código abierto para trabajar con archivos ZIP en Swift. Es compatible con iOS, macOS, tvOS y watchOS. Instalación a través de Swift Package Manager:
// En Package.swift o a través de Xcodedependencies: [ .package(url: "https://github.com/weichsel/ZIPFoundation.git", from: "0.9.0")]Funcionalidades principales de ZipFoundation:
- Creación de archivos ZIP a partir de archivos y carpetas
- Extracción de archivos individuales o de todo el archivo
- Soporte de contraseñas (AES-256)
- Trabajo con flujos para archivos grandes
- Compatibilidad con macOS e iOS
Ejemplo 1: Creación de un archivo ZIP
import ZIPFoundationimport Foundation
func createZip(from sourceURL: URL, to destinationURL: URL) throws { let fileManager = FileManager() // Crear archivo a partir de una carpeta try fileManager.zipItem(at: sourceURL, to: destinationURL) // O a partir de un solo archivo // try fileManager.zipItem(at: sourceURL, to: destinationURL, // shouldKeepParent: false)}
// Usolet documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!let sourceFolder = documents.appendingPathComponent("MyData")let archiveURL = documents.appendingPathComponent("backup.zip")
do { try createZip(from: sourceFolder, to: archiveURL) print("Archivo creado: \\(archiveURL.path)")} catch { print("Error: \\(error)")}Ejemplo 2: Descompresión de un archivo ZIP
import ZIPFoundation
func unzipArchive(at sourceURL: URL, to destinationURL: URL) throws { let fileManager = FileManager() // Crear carpeta de destino si no existe try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true) // Descomprimir try fileManager.unzipItem(at: sourceURL, to: destinationURL)}
// Usolet archiveURL = documents.appendingPathComponent("backup.zip")let extractFolder = documents.appendingPathComponent("ExtractedData")
do { try unzipArchive(at: archiveURL, to: extractFolder) print("Descompresión completada")} catch {