العمل مع أرشيفات ZIP في Swift (iOS/macOS)
في التطوير الحديث لنظامي iOS وmacOS، غالبًا ما تكون هناك حاجة لضغط الملفات في أرشيفات ZIP أو استخراج البيانات منها. قد يكون ذلك ضروريًا لتوفير المساحة، أو نقل البيانات عبر الشبكة، أو تنظيم النسخ الاحتياطية. في هذه المقالة، سنستعرض طريقتين رئيسيتين: استخدام الإمكانيات المدمجة في Foundation ومكتبة الطرف الثالث الشهيرة ZipFoundation.
الأدوات المدمجة في Foundation (NSFileCoordinator + العمل منخفض المستوى)
لا توفر Apple واجهة برمجة تطبيقات عالية المستوى للعمل مع ZIP في Foundation. ومع ذلك، بدءًا من iOS 12 / macOS 10.14، أصبح من الممكن استخدام NSFileCoordinator و NSFileWrapper لبعض العمليات. ولكن للعمل الكامل مع ZIP، غالبًا ما يتم استخدام الأداة النظامية libz عبر واجهة C.
مثال: ضغط البيانات باستخدام 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}مكتبة ZipFoundation (الطريقة الموصى بها)
ZipFoundation هي مكتبة خفيفة الوزن مفتوحة المصدر للعمل مع أرشيفات ZIP في Swift. تدعم iOS وmacOS وtvOS وwatchOS. التثبيت عبر Swift Package Manager:
// في Package.swift أو عبر Xcodedependencies: [ .package(url: "https://github.com/weichsel/ZIPFoundation.git", from: "0.9.0")]الإمكانيات الرئيسية لـ ZipFoundation:
- إنشاء أرشيفات ZIP من الملفات والمجلدات
- استخراج ملفات فردية أو الأرشيف بأكمله
- دعم كلمات المرور (AES-256)
- العمل مع التدفقات للملفات الكبيرة
- التوافق مع macOS وiOS
مثال 1: إنشاء أرشيف ZIP
import ZIPFoundationimport Foundation
func createZip(from sourceURL: URL, to destinationURL: URL) throws { let fileManager = FileManager() // إنشاء أرشيف من مجلد try fileManager.zipItem(at: sourceURL, to: destinationURL) // أو من ملف واحد // try fileManager.zipItem(at: sourceURL, to: destinationURL, // shouldKeepParent: false)}
// الاستخدامlet 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("تم إنشاء الأرشيف: \\(archiveURL.path)")} catch { print("خطأ: \\(error)")}مثال 2: فك ضغط أرشيف ZIP
import ZIPFoundation
func unzipArchive(at sourceURL: URL, to destinationURL: URL) throws { let fileManager = FileManager() // إنشاء مجلد الوجهة إذا لم يكن موجودًا try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true) // فك الضغط try fileManager.unzipItem(at: sourceURL, to: destinationURL)}
// الاستخدامlet archiveURL = documents.appendingPathComponent("backup.zip")let extractFolder = documents.appendingPathComponent("ExtractedData")
do { try unzipArchive(at: archiveURL, to: extractFolder) print("تم الانتهاء من فك الضغط")} catch {