مقدمة: لماذا Swift مناسب لـ REST API؟
\n\nعندما يتعلق الأمر بتطوير الخادم، فإن Swift ليس أول لغة تتبادر إلى الذهن. ومع ذلك، مع ظهور إطار العمل Vapor (وبديله Kitura)، أصبح Swift أداة كاملة لإنشاء REST API. لماذا نستخدم Swift على الخادم؟ أولاً، إنها لغة موحدة لنظامي iOS وmacOS والواجهة الخلفية - يمكنك إعادة استخدام نماذج البيانات. ثانيًا، Swift سريع وآمن ويدعم بشكل ممتاز البرمجة غير المتزامنة من خلال async/await.
\n\nفي هذا الدليل، سننشئ REST API بسيطًا لإدارة قائمة المهام (Todo list) بلغة Swift باستخدام إطار العمل Vapor. ستتعلم كيفية إعداد الخادم، وإنشاء المسارات، والعمل مع JSON، واختبار API. ستستغرق العملية بأكملها حوالي 30 دقيقة.
\n\nالخطوة 1: تثبيت وإعداد المشروع
\n\nقبل كتابة الكود، تحتاج إلى تثبيت Vapor Toolbox - أداة سطر الأوامر لإنشاء وإدارة مشاريع Vapor.
\n\nتثبيت Vapor Toolbox
\nافتح الطرفية ونفذ:
\nbrew install vapor\nإذا لم يكن لديك Homebrew، قم بتثبيته من brew.sh.
\n\nإنشاء مشروع جديد
\nلننشئ مشروعًا جديدًا باسم TodoAPI:
vapor new TodoAPI -n\ncd TodoAPI\nالعلامة -n تعني "بدون مثال" - سنحصل على قالب نظيف.
تشغيل الخادم
\nافتح المشروع في Xcode:
\nopen Package.swift\nاختر المخطط Run واضغط Cmd+R. بعد بضع ثوانٍ، سيبدأ الخادم على http://127.0.0.1:8080. افتح المتصفح - يجب أن ترى رسالة ترحيب من Vapor.
الخطوة 2: إنشاء نموذج البيانات
\n\nسيدير API الخاص بنا المهام. كل مهمة تحتوي على معرف وعنوان وحالة الإنجاز (مكتملة/غير مكتملة).
\n\nلننشئ نموذج Todo. في Vapor، النماذج هي هياكل عادية تتوافق مع بروتوكول Content (للتسلسل إلى JSON) وCodable.
أنشئ ملف Sources/App/Models/Todo.swift:
\nimport Vapor\n\nstruct Todo: Content, Codable {\n var id: UUID?\n var title: String\n var isCompleted: Bool\n \n init(id: UUID? = nil, title: String, isCompleted: Bool = false) {\n self.id = id\n self.title = title\n self.isCompleted = isCompleted\n }\n}\n\nلاحظ: id هو UUID اختياري. سنقوم بتوليده على الخادم عند إنشاء المهمة.
الخطوة 3: إنشاء المخزن والتحكم
\n\nللبساطة، سنخزن المهام في الذاكرة (في مصفوفة). في مشروع حقيقي، ستستخدم قاعدة بيانات (Fluent ORM)، ولكن لعرض توضيحي مدته 30 دقيقة، هذا مفرط.
\n\nالمخزن (In-Memory Store)
\nأنشئ ملف Sources/App/Controllers/TodoStore.swift:
\nimport Vapor\n\nfinal class TodoStore {\n private var todos: [Todo] = []\n private let lock = NSLock()\n \n func getAll() -> [Todo] {\n lock.lock()\n defer { lock.unlock() }\n return todos\n }\n \n func get(id: UUID) -> Todo? {\n lock.lock()\n defer { lock.unlock() }\n return todos.first { $0.id == id }\n }\n \n func create(_ todo: inout Todo) -> Todo {\n lock.lock()\n defer { lock.unlock() }\n todo.id = UUID()\n todos.append(todo)\n return todo\n }\n \n func update(id: UUID, with updatedTodo: Todo) -> Todo? {\n lock.lock()\n defer { lock.unlock() }\n guard let index = todos.firstIndex(where: { $0.id == id }) else { return nil }\n var mutableTodo = updatedTodo\n mutableTodo.id = id\n todos[index] = mutableTodo\n return mutableTodo\n }\n \n func delete(id: UUID) ->