كيفية معرفة نوع المتغير في Swift: دليل كامل مع أمثلة برمجية

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا تحتاج إلى معرفة نوع المتغير في Swift؟

\n

هل سبق لك أن كتبت كودًا بلغة Swift وفجأة تساءلت: "ما هو نوع هذا المتغير؟" خاصة عند العمل مع Any، أو الأدوية (Generics)، أو الوراثة المعقدة. الأمر يشبه محاولة تخمين ما بداخل صندوق دون فتحه. لكن في Swift، هناك أدوات قوية تسمح لك بالنظر إلى الداخل وتحديد نوع أو كلاس المتغير بدقة.

\n

في هذه المقالة، سنشرح كيفية عرض نوع المتغير في Swift باستخدام type(of:)، Mirror، String(describing:) وحتى dynamicType القديم الجيد (نعم، لا يزال موجودًا في الكود القديم). ستتعلم ليس فقط طباعة النوع، بل أيضًا استخدامه في مشاريع حقيقية: لتصحيح الأخطاء، وتسجيل السجلات، والتحقق من الأنواع في وقت التشغيل، والعمل مع البروتوكولات.

\n

المقالة مكتوبة للموقع التعليمي pythonlib.ru ومُكيَّفة للمبتدئين والمطورين ذوي الخبرة. هيا بنا!

\n\n

1. الطريقة الأبسط: type(of:)

\n

الطريقة الأكثر شيوعًا وصحة لمعرفة نوع المتغير في Swift هي استخدام الدالة العامة type(of:). تقوم هذه الدالة بإرجاع النوع الفوقي (MetaType) للقيمة المُمررة.

\n

مثال:

\n
let name = "آنا"\nlet age = 25\nlet price: Double = 99.99\nlet isActive = true\n\nprint(type(of: name))   // String\nprint(type(of: age))    // Int\nprint(type(of: price))  // Double\nprint(type(of: isActive)) // Bool\n
\n

لاحظ أن type(of:) يعمل مع أي نوع — الهياكل (Structs)، الكلاسات (Classes)، التعدادات (Enums)، والإغلاقات (Closures). حتى مع القيم الاختيارية:

\n
var optionalValue: String? = "Hello"\nprint(type(of: optionalValue)) // Optional<String>\n
\n\n

لماذا type(of:) هو الخيار الأفضل؟

\n
    \n
  • يعمل مع أنواع القيم (الهياكل، التعدادات) وأنواع المراجع (الكلاسات).
  • \n
  • يدعم البروتوكولات والأدوية (Generics).
  • \n
  • لا يتطلب تحديد النوع صراحة في الكود.
  • \n
  • يُرجع النوع الديناميكي الدقيق (مع مراعاة الوراثة).
  • \n
\n\n

2. الطريقة التقليدية: String(describing:)

\n

أحيانًا لا تحتاج فقط إلى معرفة النوع، بل إلى تحويله إلى سلسلة نصية لعرضها في السجل أو الواجهة. String(describing:) يقوم بهذه المهمة بشكل ممتاز:

\n
let value: Any = 42\nprint(String(describing: type(of: value))) // Int\n
\n

يمكن دمجه مع type(of:) لتسجيل جميل:

\n
func logType(_ value: Any) {\n    let typeName = String(describing: type(of: value))\n    print("[LOG] النوع: \\(typeName)، القيمة: \\(value)")\n}\nlogType(3.14)  // [LOG] النوع: Double، القيمة: 3.14\n
\n\n

3. العمل مع الكلاسات: dynamicType و Mirror

\n

قبل Swift 3، كان يُستخدم الخاصية dynamicType. لا تزال متاحة للتوافق مع الإصدارات السابقة، لكنها مُهمَلة رسميًا. ومع ذلك، قد تجدها في المشاريع القديمة:

\n
class Animal {}\nclass Dog: Animal {}\n\nlet pet: Animal = Dog()\nprint(pet.dynamicType) // Dog (بناء جملة قديم)\n
\n

البديل الحديث هو type(of:):

\n
print(type(of: pet)) // Dog\n
\n\n

Mirror: نظرة أعمق

\n

إذا كنت بحاجة إلى معرفة ليس فقط النوع، بل أيضًا بنية الكائن (مثل أسماء الخصائص)، استخدم Mirror:

\n
struct User {\n    let name: String\n    let age: Int\n}\n\nlet user = User(name: "إيفان", age: 30)\nlet mirror = Mirror(reflecting: user)\nprint(mirror.subjectType) // User\nfor child in mirror.children {\n    print("\\(child.label ?? ""): \\(child.value) (\\(type(of: child.value)))")\n}\n// الإخراج:\n// name: إيفان (String)\n// age: 30 (Int)\n
\n

هذا مفيد بشكل خاص لتصحيح أخطاء التسلسلات الهرمية المعقدة أو عند العمل مع الانعكاس (Reflection).

\n\n

4. تحديد الكلاس لـ Any و AnyObject

\n

في Swift، غالبًا ما نواجه النوع Any — يمكنه تخزين قيمة من أي نوع. لمعرفة النوع المحدد

المدونات

توصيات الكتب