أي مقابل AnyObject في سويفت 3.0

عندما واجهت هذين النوعين من الأسماء المستعارة للنوع أثناء تحليل بيانات JSON لأول مرة ، لم يكن لدي أي فكرة عن كيفية التمييز بينها أو تنفيذها بشكل صحيح. اذن ما هم؟ Any و AnyObject هما نوعان خاصان في Swift يُستخدمان للعمل مع أنواع غير محددة.

وفقًا لوثائق Apple Swift ،

  • يمكن لأيٍ أن يمثل مثيلًا لأي نوع على الإطلاق ، بما في ذلك أنواع الوظائف والأنواع الاختيارية.
  • يمكن أن يمثل AnyObject مثيلًا لأي نوع فئة.

حسنًا ، بسيط بما فيه الكفاية - يتم استخدام أي شيء لجميع الأنواع ، يتم استخدام AnyObject لأنواع الفصل ، أليس كذلك؟

لفهم كيف يتصرفون فعليًا في الكود ، قررت أن ألعب معهم في ملعب.

أي مثال

أي سمح لي بالعمل مع مزيج من أنواع مختلفة بما في ذلك أنواع الوظائف وغير الفئة مثل Int و String و Bool. وفقًا للوثائق ، فإن العناصر الموجودة في هذا الصفيف هي بنيات هي أنواع قيم ، لذلك من الناحية النظرية ، يجب ألا يعمل AnyObject في هذه الحالات.

للتحقق من ذلك ، حاولت تضمين سلاسل و Ints ، وهي أنواع قيم في Swift ، باستخدام AnyObject.

خطأ AnyObjectArray عند تضمين أنواع البنية

كما هو متوقع ، قام برنامج التحويل البرمجي برمي خطأ يفيد بأن العناصر لا تتوافق مع النوع AnyObject في الصفيف. مسكتك!

بعد ذلك ، حدث هذا الشيء الغريب عندما حاولت اتباع اقتراحات المترجم:

عناصر مسبوكة إلى AnyObject

ماذا حدث للتو؟! كيف تمكنت من استخدام AnyObject على Ints و Strings من خلال نقل كل عنصر بشكل صريح إلى AnyObject؟

ثم قمت بطباعة anyObjectArray في وحدة التحكم.

طباعة anyObjectArray

من الواضح أن عنصر Hi يبدو كسلسلة بالنسبة لي ، لكن لم يكن لديه علامات اقتباس مثل قيمة سلسلة عادية في Swift!

بعد ذلك ، قمت بطباعة كل عنصر باستخدام حلقة for-in للتحقق من نوعه الفعلي بدلاً من نوع AnyObject الخاص به.

أولاً ، لقد استخدمت عامل التشغيل لمعرفة ما إذا كانت العناصر هي أنواع Swift Structure أم لا.

التحقق من أنواع العناصر في anyObjectArray 1

إنه من النوع String! ثم كيف يمكن أن يلقي على AnyObject؟ مرة أخرى ، السلاسل في Swift عبارة عن بنيات وليست أنواعًا للفئات. وبالتالي من الناحية النظرية ، لا ينبغي أن أكون قادرًا على طرحها على أنها AnyObject.

ماذا؟

كنت في حيرة من أمري ، وقررت القيام ببعض التجارب معها. هذه المرة ، استخدمت NSNumber و NSString ، وهما من أنواع Objective-C ، للتحقق من نوع كل عنصر.

التحقق من أنواع العناصر في anyObjectArray 2

انتظر ، Hi هي أيضًا NSString والعناصر الرقمية هي NSNumber! و ... أنها أنواع مرجعية في الهدف- C! هل كان هذا هو السبب وراء عدم وجود Hi على علامات اقتباس عليها في وحدة التحكم؟ لقد كتبت بعض التعليمات البرمجية كما هو موضح أدناه لمعرفة ما إذا كان افتراضي صحيحًا أم لا.

طباعة NSString Array و String Arrayمرحبًا مع عدم وجود اقتباسات في وحدة التحكم مثل NSString

تم تأكيد! تعتبر العناصر التي يتم تحويلها إلى AnyObject في الصفيف الآن أنواع فئة من Object-C: NSString و NSNumber.

إذن ... ما الذي يحدث بالفعل تحت الغطاء؟ واصلت البحث في هذا الموضوع ووجدت الإجابة الأكثر منطقية من المستند باستخدام Swift with Cocoa and Objective-C (Swift 3.0.1).

كجزء من قابلية التشغيل البيني مع الهدف- C ، تقدم Swift طرقًا مريحة وفعالة للعمل مع أطر الكاكاو. يقوم Swift تلقائيًا بتحويل بعض أنواع Objective-C إلى أنواع Swift ، وبعض أنواع Swift إلى أنواع Objective-C. يُشار إلى الأنواع التي يمكن تحويلها بين Objective-C و Swift بأنواع الجسور.
في أي مكان يمكنك استخدام نوع مرجعي Objective-C له جسر ، يمكنك استخدام نوع قيمة Swift بدلاً من ذلك. يتيح لك ذلك الاستفادة من الوظيفة المتوفرة في تطبيق نوع المرجع بطريقة طبيعية في كود Swift. لهذا السبب ، يجب ألا تحتاج أبدًا إلى استخدام نوع مرجعي مرتبط مباشرة في الكود الخاص بك. في الواقع ، عندما يقوم رمز Swift باستيراد APIs Objective-C ، يستبدل المستورد أنواع مرجعية Objective-C بأنواع القيمة المقابلة لها. وبالمثل ، عندما يقوم كود Object-C باستيراد واجهات برمجة التطبيقات لـ Swift ، يستبدل المستورد أيضًا أنواع قيم Swift بأنواع مراجع Objective-C المقابلة لها. "

بمعنى آخر ، يبذل المترجم قصارى جهده ليكون مرنًا في التعامل مع مثل هذه الأنواع من خلال التحويل التلقائي والجسور مع منع تطبيقنا من التعطل بسهولة. متألق!

إذن متى نستخدم بالفعل AnyObject؟ كما هو مذكور في وثائق Apple ، يمكن استخدام AnyObject للعمل مع الكائنات المشتقة من Class والتي لا تشارك فئة جذر شائعة.

ولكن هل من الضروري للغاية استخدامه في التعليمات البرمجية لدينا؟

جوابي على هذا السؤال هو: لا.

أبل تقول:

في Swift 3 ، يتم الآن تحديد نوع المعرف في Objective-C إلى أي نوع في Swift ، الذي يصف قيمة أي نوع ، سواء كانت فئة أو تعداد أو بنية أو أي نوع آخر من Swift. يجعل هذا التغيير واجهات برمجة التطبيقات Objective-C أكثر مرونة في Swift ، لأنه يمكن تمرير أنواع القيم المعرفة من Swift إلى واجهات برمجة التطبيقات Objective-C واستخراجها كنوع من أنواع Swift ، مما يلغي الحاجة لأنواع "الصندوق" اليدوية.
تمتد هذه الفوائد أيضًا إلى المجموعات: أنواع مجموعات Objective-C NSArray و NSDictionary و NSSet ، والتي قبلت سابقًا عناصر AnyObject فقط ، يمكنها الآن الاحتفاظ بعناصر من أي نوع. بالنسبة للحاويات المجزأة ، مثل Dictionary and Set ، هناك نوع جديد AnyHashable يمكنه الاحتفاظ بقيمة من أي نوع يتوافق مع بروتوكول Swift Hashable.

يبدو أن أي شخص يعمل بشكل جيد تمامًا في سد هاتين اللغتين في Swift 3 دون الحاجة إلى استخدام AnyObject!

إذن ما هو السبب النهائي وراء هذه التغييرات؟

بكلماتهم الخاصة ، تشرح Apple:

واجهات Swift 3 مع واجهات برمجة التطبيقات Objective-C بطريقة أقوى من الإصدارات السابقة. على سبيل المثال ، قام Swift 2 بتعيين نوع المعرف في Objective-C لنوع AnyObject في Swift ، والذي يمكنه عادة الاحتفاظ بقيم أنواع الفئات فقط. قدم Swift 2 أيضًا تحويلات ضمنية إلى AnyObject لبعض أنواع القيم المربوطة ، مثل String و Array و Dictionary و Set و بعض الأرقام ، كراحة حتى يمكن استخدام أنواع Swift الأصلية بسهولة مع واجهات برمجة تطبيقات Cocoa التي تتوقع NSString و NSArray ، أو فئات الحاويات الأخرى من Foundation. كانت هذه التحويلات غير متسقة مع بقية اللغة ، مما يجعل من الصعب فهم ما يمكن أن يستخدم بالضبط AnyObject ، مما أدى إلى الأخطاء.

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

في الواقع ، توصي شركة Apple بما يلي:

استخدم Any و AnyObject فقط عندما تحتاج صراحة إلى السلوك والقدرات التي توفرها. من الأفضل دائمًا أن تكون محددًا بشأن الأنواع التي تتوقع أن تعمل بها في الشفرة الخاصة بك.

فكر في هذا السيناريو: نحن نعمل مع الرقم 12.5 في Swift. في هذه الحالة ، نذكر بشكل خاص أنه نوع من أنواع Double أو Float بدلاً من إعلانه من النوع Any. بهذه الطريقة ، يمكننا الوصول بسهولة إلى الخصائص أو الطرق المختلفة المتاحة لهذا النوع المحدد. في هذا السياق ، سوف نستخدم AnyObject لأنواع الفصل لأنها أكثر تحديدًا بقليل من أي. ولكن مرة أخرى ، فإن استخدام AnyObject هو مجرد خيار.

آمل أن يكون منشور المدونة هذا قد ساعد العديد من مطوريك الرائعين في توضيح Any و AnyObject. استخدم أي بثقة في Swift 3 أثناء العمل مع واجهات برمجة التطبيقات المدعومة Objective-C.

شكرا لك على القراءة والترميز سعيدة!