
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
.

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