swift - كيف يمكنني جعل إشارة بروتوكول ضعيفة في سويفت "نقية"(بدونobjc)




delegates swift-protocols (4)

لا يبدو أن المراجع weak تعمل في Swift ما لم يتم الإعلان عن protocol كـ @objc ، والذي لا أريده في تطبيق Swift خالص.

يعطي هذا الرمز خطأ ترجمة (لا يمكن تطبيق weak على النوع غير الصنف MyClassDelegate ):

class MyClass {
  weak var delegate: MyClassDelegate?
}

protocol MyClassDelegate {
}

أحتاج إلى بادئة البروتوكول مع @objc ، ثم يعمل.

سؤال: ما هي الطريقة السريعة "الصرفة" لإنجاز delegate weak ؟


الجواب التكميلي

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

  • الغرض من استخدام الكلمة الرئيسية weak هو تجنب الدورات المرجعية القوية (الاحتفاظ بالمرحلة). تحدث دورات مرجعية قوية عندما يكون لمثيلين من فئتي مراجع قوية لبعضهما البعض. لم تعد أعدادهم المرجعية صفراً أبداً حتى لا يتم إخفاؤهم أبداً.

  • تحتاج فقط إلى استخدام weak إذا كان المفوض فئة. إن بنية Swif و enums هي أنواع قيم (يتم نسخ قيمها عند إنشاء مثيل جديد) ، وليس أنواع مرجع ، لذلك فهي لا تقوم بإجراء دورات مرجعية قوية.

  • weak المراجع weak اختيارية دائمًا (وإلا إذا كنت تستخدم unowned ) وتستخدم دائمًا var (لا let ) بحيث يمكن ضبط الخيار الاختياري على nil عند إلغاء تخصيصه.

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

  • يجب استخدام weak عندما ترغب في الإشارة إلى فصل لا تملكه ، ليس فقط بالنسبة للطفل الذي يشير إلى والدته. عندما تحتاج فئتان غير هرمية إلى الإشارة لبعضهما البعض ، اختر واحدة لتكون ضعيفة. الشخص الذي تختاره يعتمد على الوضع. انظر الإجابات على هذا السؤال لمزيد من المعلومات حول هذا الموضوع.

  • كقاعدة عامة ، يجب وضع علامة على المندوبين على أنهم weak لأن معظم المندوبين يشيرون إلى فئات لا يمتلكونها. هذا صحيح بالتأكيد عندما يستخدم الطفل مفوضاً للتواصل مع أحد الوالدين. ومع ذلك ، لا تزال هناك بعض الحالات التي يمكن للمفوض فيها استخدام مرجع قوي ويجب عليه ذلك.

  • يمكن استخدام البروتوكولات لأنواع المرجع (الفئات) وأنواع القيم (التركيبات ، التعدادات). لذا في الحالة المحتملة التي تحتاج إليها لجعل مندوبًا ضعيفًا ، يجب عليك إضافة الكلمة الرئيسية class إلى البروتوكول حتى يعرف أنها تستخدم فقط مع أنواع المراجع.

    protocol MyClassDelegate: class {
        // ...
    }
    
    class SomeClass {
        weak var delegate: MyClassDelegate?
    }
    

المزيد من الدراسة

قراءة المقالات التالية هو ما ساعدني على فهم هذا أفضل بكثير. كما يناقشون أيضًا المشكلات ذات الصلة مثل الكلمة الرئيسية unowned والدورات المرجعية القوية التي تحدث مع عمليات الإغلاق.

ذات صلة


تحتاج إلى إعلان نوع البروتوكول class .

protocol ProtocolNameDelegate: class {
    // Protocol stuff goes here
}

class SomeClass {
    weak var delegate: ProtocolNameDelegate?
}

ما أفهمه هو أنه باستخدام class ، فإنك تضمن أن هذا البروتوكول سيتم استخدامه فقط في الفصول الدراسية وأشياء أخرى مثل التعدادات أو البنى.


AnyObject هي الطريقة الرسمية لاستخدام مرجع ضعيف في Swift.

class MyClass {
    weak var delegate: MyClassDelegate?
}

protocol MyClassDelegate: AnyObject {
}

من ابل:

لمنع دورات مرجعية قوية ، يجب أن يتم الإعلان عن المفوضين كمراجع ضعيفة. لمزيد من المعلومات حول المراجع الضعيفة ، راجع الدورات المرجعية القوية بين مثيلات Class. سيسمح لك وضع علامة على البروتوكول كطبقة فقط فيما بعد بإعلان أنه يجب على المفوض استخدام مرجع ضعيف. تقوم بتمييز بروتوكول على أنه يتم فقط الفصل من خلال الموروث من AnyObject ، كما هو موضح في البروتوكولات Class-Only.

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276


تحديث: يبدو أنه تم تحديث الدليل وتمت إزالة المثال الذي كنت أشير إليه. راجع التعديل على الإجابة على @ flainez أعلاه.

الأصل: استخدامobjc هو الطريقة الصحيحة للقيام بذلك حتى إذا كنت لا تعمل مع Obj-C. يضمن أن البروتوكول الخاص بك يتم تطبيقه على فئة وليس التعداد أو البنية. راجع "التحقق من توافق البروتوكول" في الدليل.







swift-protocols