مقدمة: لماذا حتى append يمكن أن يكسر الكود؟
\n\nقد يبدو الأمر بسيطًا، فما أسهل من إضافة عنصر إلى مصفوفة في Swift؟ نكتب array.append(newElement) وتنتهي المهمة. ومع ذلك، استنادًا إلى آلاف المشاهدات على Stack Overflow، فإن هذه العملية التي تبدو تافهة، تحيّر المبتدئين والمطورين ذوي الخبرة على حد سواء.
في هذه المقالة، لن نعرض فقط كيفية إضافة عنصر إلى مصفوفة في Swift. بل سنحلل أكثر 5 أخطاء شيوعًا وخبثًا التي تحول عملية append البسيطة إلى صداع. ستتعرف على سبب اعتراض المترجم على كود يبدو صحيحًا، وكيف لا تتجاوز حدود المصفوفة، وما الفرق بين append و insert. هيا بنا!
الخطأ رقم 1: نسيان الكتابة الصارمة للأنواع
\n\nSwift هي لغة ذات كتابة صارمة للأنواع. هذا يعني أن المصفوفة المُعلنة كـ [Int] لن تقبل سلسلة نصية، حتى لو كانت تشبه الرقم كثيرًا. هذا فخ شائع لمن أتى من Python أو JavaScript.
المشكلة: عدم تطابق الأنواع
\n\nvar numbers: [Int] = [1, 2, 3]\n// خطأ في الترجمة: Cannot convert value of type 'String' to expected argument type 'Int'\nnumbers.append("4")\n\n\nالحل: تحويل الأنواع
\n\nقم دائمًا بتحويل البيانات بشكل صريح إلى نوع المصفوفة. استخدم المُهيئات أو التحويل الصريح:
\n\nvar numbers: [Int] = [1, 2, 3]\nif let intValue = Int("4") {\n numbers.append(intValue) // ✅ يعمل: numbers = [1, 2, 3, 4]\n}\n\n// أو لمصفوفة نصية:\nvar strings: [String] = ["a", "b"]\nstrings.append(String(42)) // ✅ تمت إضافة "42" كسلسلة نصية\n\n\nنصيحة: إذا كنت تضيف عناصر من مصدر خارجي (API، إدخال مستخدم)، تحقق دائمًا من النوع باستخدام as? أو استخدم compactMap لتصفية القيم nil.
الخطأ رقم 2: Index out of range عند استخدام insert
\n\nتتيح لك طريقة insert(_:at:) إدراج عنصر في موضع عشوائي. ولكن إذا حددت فهرسًا أكبر من عدد العناصر في المصفوفة، سيتعطل التطبيق مع Fatal error: Index out of range.
المشكلة: الإدراج خارج حدود المصفوفة
\n\nvar fruits = ["تفاحة", "موز"]\n// مصفوفة من عنصرين: المؤشرات 0 و 1\n// خطأ! المؤشر 5 غير موجود\nfruits.insert("برتقال", at: 5)\n\n\nالحل: التحقق من الحدود والإضافة الآمنة
\n\nهناك طريقتان لتجنب هذا الخطأ:
\n- \n
- التحقق من المؤشر: تأكد من أن المؤشر يقع في النطاق من 0 إلى
array.count(بما في ذلكinsert). \n - الإكمال التلقائي: إذا كنت تريد إدراج العنصر في النهاية عند تجاوز الحدود، استخدم منطقًا مع
append. \n
var fruits = ["تفاحة", "موز"]\n\n// الخيار الآمن 1: التحقق\nlet index = 5\nif index >= 0 && index <= fruits.count {\n fruits.insert("برتقال", at: index)\n} else {\n // إذا كان المؤشر أكبر من count، أضف في النهاية\n fruits.append("برتقال")\n}\nprint(fruits) // ["تفاحة", "موز", "برتقال"]\n\n// الخيار الآمن 2: الإضافة (extension)\nextension Array {\n mutating func safeInsert(_ element: Element, at index: Int) {\n if index >= 0 && index <= self.count {\n self.insert(element, at: index)\n } else {\n self.append(element)\n }\n }\n}\n\nfruits.safeInsert("كيوي", at: 100) // ✅ سيضيف في النهاية\n\n\nالخطأ رقم 3: الخلط بين append و +=
\n\nيمكن للعامل += أيضًا إضافة عناصر، لكن سلوكه يختلف عن append. الفرق الرئيسي: += يعمل مع المجموعات وليس مع العناصر الفردية.
المشكلة: إنشاء مصفوفة ضمنيًا
\n\nvar list = [1, 2, 3]\nlis