iOS Responder Chain atau Apa yang mereka tanyakan pada saat wawancara

gambar


Apa perbedaan antara contoh pertama dan kedua?

Untuk apa target bertanggung jawab?

Dalam hal apa metode dipanggil ketika tombol diklik?

TL; DR


Ketika sebuah tombol diklik, metode kami dipanggil dalam kedua kasus.


Hanya pada contoh pertama, UIKit akan mencoba memanggil metode dalam target yang ditetapkan (kami memiliki ViewController ). Ini akan macet jika metode ini tidak ada.


Pada contoh kedua, Rantai Responder iOS digunakan, UIKit akan mencari UIResponder terdekat -a yang memiliki metode ini. Tidak akan ada kerusakan jika metode kami tidak ditemukan.


UIViewController, UIView, UIApplication UIResponder mewarisi dari UIResponder .


iOS Responder Chain dan apa yang ada di bawah tenda


UIKit proses Rantai Penanggap iOS ditangani oleh UIKit , yang bekerja secara dinamis dengan daftar UIResponder . Daftar UIKit dibuat dari responden pertama (responden UIResponder pertama yang mendaftarkan acara, kami memiliki UIButton(UIView) dan subviews .


gambar


UIKit menelusuri daftar UIResponder dan memeriksa dengan canPerformAction untuk fungsi kita.


 open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool 

Jika UIResponder terpilih tidak dapat bekerja dengan metode tertentu,
UIKit secara rekursif mengirimkan tindakan ke UIResponder berikutnya dalam daftar menggunakan metode target yang mengembalikan UIResponder berikutnya.


 open func target(forAction action: Selector, withSender sender: Any?) -> Any? 

Proses ini diulangi sampai salah satu UIResponder dapat bekerja dengan metode kami atau daftar berakhir dan sistem mengabaikan acara ini.


Pada contoh klik kedua, ditangani oleh UIViewController , tetapi UIKit pertama kali mengirim permintaan ke UIView karena itu adalah responden pertama. Dia tidak memiliki metode yang diperlukan, sehingga UIKit mengalihkan tindakan ke UIResponder berikutnya dalam daftar tertaut yang merupakan UIViewController yang memiliki metode yang diinginkan.


Dalam sebagian besar kasus, iOS Responder Chain adalah daftar sederhana subviews -tautan yang subviews , tetapi urutannya dapat diubah. Anda dapat menjadikan UIResponder (becomeFirstResponder) menjadi
UIResponder pertama dan kembalikan ke posisi lama menggunakan resignFirstResponder . Ini sering digunakan dengan UITextField untuk menunjukkan keyboard yang akan dipanggil hanya ketika UITextField adalah first responder .


iOS Responder Chain dan UIEvent


Rantai Responder juga terlibat dalam menyentuh layar, gerakan, klik. Ketika sistem mendeteksi beberapa jenis peristiwa (sentuh, gerakan, kendali jarak jauh, tekan), UIEvent dibuat di bawah tenda dan dikirim menggunakan metode UIApplication.shared.sendEvent() ke UIWindow . Setelah menerima acara tersebut, UIWindow menentukan menggunakan metode hitTest:withEvent yang UIResponder oleh UIResponder acara ini dan menetapkannya sebagai first responder . Berikutnya adalah pekerjaan dengan daftar UIResponder atas.


Untuk bekerja dengan UIEvent sistem, subclass dari UIResponder (UIViewController, UIView, UIApplication) dapat mengganti metode ini:


 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?) 

Terlepas dari kenyataan bahwa kemampuan untuk mewarisi dan memanggil sendEvent secara manual ada, UIResponder tidak dimaksudkan untuk ini. Hal ini dapat menimbulkan banyak masalah dengan pengoperasian acara khusus, yang dapat menyebabkan tindakan yang tidak dapat dipahami yang disebabkan oleh first responeder acak yang dapat menanggapi acara Anda.


Apa yang berguna, dimana harus digunakan


Terlepas dari kenyataan bahwa iOS Responder Chain sepenuhnya dikendalikan oleh UIKit , itu dapat digunakan untuk menyelesaikan masalah delegasi / komunikasi. Tindakan UIResponder mirip dengan NotificationCenter.default.post satu kali.


Mari kita ambil contoh, kita memiliki UIViewController , yang jauh di dalam tumpukan UINavigationController dan kita perlu menceritakannya apa yang terjadi ketika sebuah tombol diklik pada layar lain. Anda dapat menggunakan pola delagate atau NotificationCenter.default.post , tetapi opsi yang cukup sederhana adalah dengan menggunakan iOS Responder Chain .


 button.addTarget(nil, action: #selector(RootVC.doSomething), for: .touchUpInside) 

Saat ditekan, metode di UIViewController akan dipanggil. #selector dapat mengambil parameter berikut:


 @objc func doSomething() @objc func doSomething(sender: Any?) @objc func doSomething(sender: Any?, event: UIEvent?) 

pengirim adalah objek yang mengirim acara - UIButton, UITextField, dan sebagainya.


Sumber Tambahan untuk Belajar [ind]:


Deskripsi yang baik tentang UIEvent, UIResponder dan beberapa contoh lanjutan (koordinator patern)
Baca lebih lanjut tentang rantai responden
Contoh rantai responden dalam praktik
Tidak terpasang di rantai responden iOS
Off Dock oleh UIResponder

Source: https://habr.com/ru/post/id464463/


All Articles