
ما هو الفرق بين المثال الأول والثاني؟
ما هو الهدف المسؤول عن؟
في هذه الحالة يتم استدعاء الأسلوب عند النقر فوق الزر؟
TL ؛ د
عند النقر فوق زر ، يتم استدعاء الأسلوب لدينا في كلتا الحالتين.
في المثال الأول فقط ، سيحاول UIKit استدعاء الطريقة في الهدف المحدد (لدينا ViewController
). سوف تتعطل إذا كانت هذه الطريقة غير موجودة.
في المثال الثاني ، يتم استخدام سلسلة مستجيب iOS ، UIKit
عن أقرب UIResponder
a الذي لديه هذه الطريقة. لن يكون هناك أي تعطل إذا لم يتم العثور على طريقة لدينا.
UIViewController, UIView, UIApplication
UIResponder
ترث من UIResponder
.
سلسلة مستجيب دائرة الرقابة الداخلية وما تحت الغطاء
تتم معالجة عملية سلسلة iOS Responder UIKit
بواسطة UIKit
، والتي تعمل ديناميكيًا مع قائمة مرتبطة من UIResponder
. UIKit
إنشاء قائمة UIKit
هذه من المستجيب الأول (أول UIResponder
الذي سجل الحدث ، لدينا UIButton(UIView)
subviews
.

UIKit يذهب من خلال قائمة UIResponder
ويتحقق مع canPerformAction
.
open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool
إذا كان لا يمكن أن تعمل UIResponder
المحدد مع طريقة محددة ،
يرسل UIKit
الإجراءات بشكل متكرر إلى UIResponder
التالي في القائمة باستخدام الطريقة target
التي تُرجع UIResponder
التالي.
open func target(forAction action: Selector, withSender sender: Any?) -> Any?
تتكرر هذه العملية حتى UIResponder
أحد UIResponder
العمل مع طريقتنا أو تنتهي القائمة ويتجاهل النظام هذا الحدث.
في المثال الثاني للنقر ، تمت معالجته بواسطة UIKit
، ولكن أرسل UIKit
أولاً طلبًا إلى UIView
لأنه كان المستجيب الأول. لم يكن لديه الطريقة المطلوبة ، لذلك قام UIKit
بإعادة توجيه الإجراءات إلى UIResponder
التالي في قائمة مرتبطة كانت UIViewController
لها الطريقة المطلوبة.
في معظم الحالات ، iOS Responder Chain
هي قائمة subviews
بسيطة من subviews
، لكن يمكن تغيير ترتيبها. يمكنك جعل UIResponder (becomeFirstResponder)
أصبح UIResponder (becomeFirstResponder)
تصبح
UIResponder
الأول وإعادته إلى الموضع القديم باستخدام resignFirstResponder
. يستخدم هذا غالبًا مع UITextField
لإظهار لوحة المفاتيح التي سيتم استدعاؤها فقط عندما يكون UITextField
هو first responder
.
دائرة الرقابة الداخلية المستجيب سلسلة و UIEvent
وتشارك سلسلة المستجيب أيضا في لمس الشاشة ، والحركات ، والنقرات. عندما يكتشف النظام نوعًا من الأحداث (اللمس ، الحركة ، التحكم عن بعد ، اضغط) ، يتم إنشاء UIEvent
تحت الغطاء ويتم إرساله باستخدام طريقة UIWindow
UIApplication.shared.sendEvent()
إلى UIWindow
. بعد تلقي الحدث ، تحدد UIWindow
استخدام hitTest:withEvent
التي ينتمي إليها UIResponder
هذا الحدث UIResponder
first responder
. التالي هو العمل مع قائمة مرتبطة بـ UIResponder
الموضحة أعلاه.
للعمل مع UIEvent
للنظام ، يمكن UIEvent
الفرعية من UIResponder (UIViewController, UIView, UIApplication)
تجاوز هذه الأساليب:
open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) open func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) open func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) open func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) open func pressesChanged(_ presses: Set<UIPress>, with event: UIPressesEvent?) open func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) open func pressesCancelled(_ presses: Set<UIPress>, with event: UIPressesEvent?) open func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) open func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) open func motionCancelled(_ motion: UIEvent.EventSubtype, with event: UIEvent?) open func remoteControlReceived(with event: UIEvent?)
على الرغم من أن القدرة على وراثة و sendEvent
يدوياً موجودة ، UIResponder
مخصص لهذا الغرض. يمكن أن يؤدي ذلك إلى إنشاء العديد من المشكلات مع تشغيل الأحداث المخصصة ، والتي يمكن أن تؤدي إلى إجراءات غير مفهومة تسببها first responeder
العشوائي الذي يمكنه الاستجابة لهذا الحدث.
لماذا هو مفيد ، حيث للاستخدام
على الرغم من حقيقة أن iOS Responder Chain
التحكم فيها بالكامل بواسطة UIKit
، إلا أنه يمكن استخدامها لحل مشكلة التفويض / التواصل. UIResponder
إجراءات UIResponder
NotificationCenter.default.post
لمرة واحدة.
دعنا نأخذ مثالا ، لدينا UIViewController
، وهو عميق في مكدس UINavigationController ونحن بحاجة إلى إخباره بما حدث عندما تم النقر على زر على شاشة أخرى. يمكنك استخدام نقش delagate أو NotificationCenter.default.post
، ولكن الخيار البسيط إلى حد ما هو استخدام iOS Responder Chain
.
button.addTarget(nil, action: #selector(RootVC.doSomething), for: .touchUpInside)
عند الضغط عليه ، سيتم استدعاء الطريقة الموجودة في UIViewController
. #selector يمكن أن تأخذ المعلمات التالية:
@objc func doSomething() @objc func doSomething(sender: Any?) @objc func doSomething(sender: Any?, event: UIEvent?)
المرسل هو الكائن الذي أرسل الحدث - UIButton و UITextField وما إلى ذلك.
موارد إضافية للتعلم [eng]:
وصف جيد لـ UIEvent و UIResponder واثنين من الأمثلة المتقدمة (منسق النداء)
اقرأ المزيد عن سلسلة استجابة دائرة الرقابة الداخلية
مثال سلسلة المستجيب في الممارسة العملية
قبالة قفص الاتهام على سلسلة دائرة الرقابة الداخلية المستجيب
قبالة قفص الاتهام من قبل UIResponder