تسلسل الكائنات في Swift (iOS/macOS)
\nالتسلسل هو عملية تحويل الكائنات المعقدة (الهياكل، الفئات، النسخ) إلى تنسيق مناسب للتخزين أو النقل عبر الشبكة (JSON، Property List، بيانات ثنائية). إلغاء التسلسل هو العملية العكسية لاستعادة الكائن من هذه البيانات. في Swift لنظامي iOS و macOS، هناك طريقتان رئيسيتان: البروتوكول الحديث Codable (ومكوناته Encodable و Decodable) والبروتوكول الأقدم NSCoding من إطار العمل Foundation. في هذه المقالة، سنشرح بالتفصيل كلا الطريقتين مع أمثلة كود.
1. بروتوكول Codable (الطريقة الموصى بها)
\nCodable هو بروتوكول يجمع بين Encodable و Decodable. يسمح بإنشاء كود التسلسل وإلغاء التسلسل تلقائيًا إذا كانت جميع خصائص الهيكل أو الفئة تتوافق أيضًا مع Codable (سلاسل نصية، أرقام، تواريخ، مصفوفات، قواميس، إلخ).
1.1. التسلسل الأساسي إلى JSON
\nلننظر إلى هيكل مستخدم بسيط:
\nimport Foundation\n\nstruct User: Codable {\n let id: Int\n var name: String\n var email: String\n}\n\n// إنشاء نسخة\nlet user = User(id: 1, name: "إيفان بيتروف", email: "ivan@example.com")\n\n// التسلسل إلى Data (JSON)\nlet encoder = JSONEncoder()\nencoder.outputFormatting = .prettyPrinted // لإخراج قابل للقراءة\n\ndo {\n let jsonData = try encoder.encode(user)\n if let jsonString = String(data: jsonData, encoding: .utf8) {\n print(jsonString)\n }\n} catch {\n print("خطأ في التسلسل: \\(error.localizedDescription)")\n}\n\n\n1.2. إلغاء التسلسل من JSON
\n// لنفترض أن لدينا سلسلة JSON\nlet jsonString = """\n{\n "id": 2,\n "name": "ماريا سميرنوفا",\n "email": "maria@test.com"\n}\n"""\n\nlet jsonData = Data(jsonString.utf8)\nlet decoder = JSONDecoder()\n\ndo {\n let decodedUser = try decoder.decode(User.self, from: jsonData)\n print("الاسم: \\(decodedUser.name)، البريد الإلكتروني: \\(decodedUser.email)")\n} catch {\n print("خطأ في إلغاء التسلسل: \\(error.localizedDescription)")\n}\n\n\n1.3. تخصيص المفاتيح (CodingKeys)
\nإذا كانت أسماء الخصائص في Swift تختلف عن المفاتيح في JSON، استخدم التعداد CodingKeys:
struct Article: Codable {\n var title: String\n var body: String\n var publicationDate: Date\n\n enum CodingKeys: String, CodingKey {\n case title\n case body\n case publicationDate = "published_at" // المفتاح في JSON\n }\n}\n\nlet articleJSON = """\n{"title":"Swift Codable","body":"نص المقالة","published_at":"2024-01-15T10:00:00Z"}\n"""\nlet articleData = Data(articleJSON.utf8)\nlet decoder = JSONDecoder()\ndecoder.dateDecodingStrategy = .iso8601 // لتحليل التاريخ بشكل صحيح\n\nif let article = try? decoder.decode(Article.self, from: articleData) {\n print("العنوان: \\(article.title)، التاريخ: \\(article.publicationDate)")\n}\n\n\n1.4. PropertyListEncoder / PropertyListDecoder
\nللتسلسل إلى تنسيق Property List (XML أو ثنائي)، استخدم PropertyListEncoder:
let plistEncoder = PropertyListEncoder()\nplistEncoder.outputFormat = .xml\n\nif let plistData = try? plistEncoder.encode(user) {\n // يمكن حفظ plistData في ملف\n let plistString = String(data: plistData, encoding: .utf8)\n print(plistString ?? "بيانات غير صالحة")\n}\n\n\n2. بروتوكول NSCoding (للفئات الموروثة من NSObject)
\nNSCoding هو بروتوكول من Objective-C لا يزال يُستخدم لتسلسل الفئات، خاصة تلك التي تعمل مع UIKit/AppKit (مثل UIView، UIViewController). يتطلب أن ترث الفئة من NSObject وتنفذ الطريقتين encode(with:) و init?(coder:).