مقدمة
Swift هي لغة برمجة قوية وبديهية للنظام البيئي لـ Apple. ومع ذلك، فإن بناء الجملة المختصر والكتابة الصارمة غالبًا ما يربكان المبتدئين. في هذه المقالة، سنقوم بتحليل الأخطاء الأكثر شيوعًا التي يرتكبها مطورو iOS و macOS المبتدئون. سننتقل من الحرف أ (العد المرجعي التلقائي - Automatic Reference Counting) إلى ي (فك تغليف الخيارات الصريح). كل نقطة مصحوبة بمثال كود حقيقي وشرح لكيفية تجنب المشكلة.
1. الأخطاء في التعامل مع Optionals (nil وفك التغليف)
واحدة من أقوى ميزات Swift هي التعامل الآمن مع nil. لكن المبتدئين غالبًا ما يتجاهلون الخيارات أو يستخدمون الاستخراج الإجباري (!) في أماكن غير آمنة.
1.1. الاستخراج الإجباري (Force Unwrapping) بدون تحقق
الخطأ الأكثر شيوعًا هو وضع علامة التعجب دون التأكد من أن القيمة لا تساوي nil.
// ❌ خطأ: سيتعطل التطبيق إذا لم يتم العثور على userlet user = users.first!print(user.name)
// ✅ صحيح: استخراج آمنif let user = users.first { print(user.name)} else { print("المستخدم غير موجود")}1.2. تجاهل guard let
يستخدم العديد من المبتدئين if let المتداخلة، مما يخلق "هرم الموت". استخدم guard let للخروج المبكر من الدالة.
// ❌ سيء: if let متداخلةfunc process(user: User?) { if let unwrappedUser = user { if let email = unwrappedUser.email { print(email) } }}
// ✅ جيد: guard letfunc process(user: User?) { guard let unwrappedUser = user, let email = unwrappedUser.email else { return } print(email)}2. إدارة الذاكرة (ARC وحلقات المراجع القوية)
يستخدم Swift العد المرجعي التلقائي (Automatic Reference Counting - ARC)، لكنه ليس سحريًا. غالبًا ما يخلق المبتدئون تسريبات في الذاكرة، متناسين التقاط الإغلاقات.
2.1. المراجع القوية في الإغلاقات
عند تمرير إغلاق يلتقط self، ويخزن self هذا الإغلاق، تنشأ حلقة.
class NetworkManager { var onComplete: (() -> Void)? func fetchData() { // ❌ خطأ: مرجع قوي لـ self onComplete = { self.updateUI() } // ✅ صحيح: مرجع ضعيف onComplete = { [weak self] in self?.updateUI() } } func updateUI() { /* ... */ }}2.2. نسيان unowned
أحيانًا تكون متأكدًا من أن الكائن لن يكون nil. استخدم [unowned self]، ولكن فقط إذا كنت تضمن أن self لن يتم تحريرها قبل الإغلاق.
// خطير: unowned مع الاستدعاءات غير المتزامنةclass ViewController { func loadImage() { ImageService.shared.fetch { [unowned self] image in // إذا تم تحرير self، سيتعطل التطبيق self.imageView.image = image } }}
// أكثر أمانًا: weakfunc loadImage() { ImageService.shared.fetch { [weak self] image in self?.imageView.image = image }}3. الفخاخ النحوية النموذجية
حتى بناء الجملة البسيط يمكن أن يكون مربكًا إذا كنت لا تعرف تفاصيل Swift.
3.1. الخلط بين الفئات (Classes) والهياكل (Structs)
غالبًا ما يجعل المبتدئون كل شيء فئة، متناسين أن الهياكل هي أنواع قيمة (value types) والفئات هي أنواع مرجعية (reference types).
// ❌ خطأ: تغيير خاصية الهيكل داخل نفسهstruct User { var name: String mutating func changeName(to newName: String) { name = newName // بدون mutating لن يتم تجميعه }}
// ✅ بالنسبة للفئة، لا حاجة لـ mutatingclass UserClass { var name: String func changeName(to newName: String) { name = newName }}3.2. الاستخدام غير الصحيح لـ defer
defer