Responder Chain iOS mexanizmidir, o, toxunma, düzmə basılmaları və jestlər hadisələrini UIResponder obyektləri iyerarxiyası vasitəsilə ardıcıl olaraq ötürür, ta ki onlardan biri hadisəni emal edənə qədər. Zəncir hadisəni aşkarlayan obyektdən başlayır və iyerarxiyada yuxarıya doğru hərəkət edir: view-dən onun superview-ə, sonra view controller-ə, window-a və nəhayət UIApplication-a. Apple Developer Documentation (2026)-ya görə, bu nümunə hadisələrin işlənməsi üçün məsuliyyəti interfeys komponentləri arasında bölməyə, müəyyən bir handler-ə sərt bağlanma olmadan çeviklik təmin etməyə imkan verir.
Əsas Məqamlar
Responder Chain iOS-un giriş hadisələrini — toxunma, düzmə basılmaları və akselerometr kimi — UIResponder obyektləri ardıcıllığı vasitəsilə ötürdüyü bir mexanizmdir. Bu zəncirdəki hər bir obyekt hadisəni emal etmək və ya növbəti responder obyektinə next xassəsi vasitəsilə ötürmək imkanına malikdir.
Mexanizm view iyerarxiyasına əsaslanır: toxunma baş verdikdə, iOS əvvəlcə hansı view-in basıldığını müəyyən edir (hit-testing vasitəsilə) və bu view-dən başlayaraq UIApplication-a qədər yüksələn bir zəncir yaradır. UIApplication zəncirin son halqasıdır — hadisə ona çatıb emal edilməzsə, sadəcə atılır.
Apple-a görə, bu nümunə hadisə emalının məntiqinin kapsullaşdırılması üçün kritik əhəmiyyət kəsb edir. Tərtibatçı, iyerarxiyanın qalan elementlərinə təsir etmədən müəyyən bir view-in davranışını əvəz edə bilər. Məsələn, UITextField fokus aldıqda first responder olur və ana UIViewController-də dəyişiklik tələb etmədən klaviatura hadisələrini qəbul edir.
Hadisələrin emalı Responder Chain vasitəsilə iki mərhələdə baş verir: əvvəlcə iOS hansı view-in hadisəni aldığını müəyyən edir (hit-testing), sonra onu emal etmək üçün responder zəncirini işə salır. Obyekt müvafiq metodu tətbiq etməzsə, hadisə daha da ötürülür.
Zəncir cari first responder və view iyerarxiyası əsasında dinamik olaraq formalaşır. Standart sıra belədir: first responder → onun view-i → superview → UIViewController → root view → UIWindow → UIApplication. Bu obyektlərdən hər hansıbiri, məsələn touchesBegan-ı tətbiq edərsə, hadisə bu səviyyədə emal edilir və daha da ötürülmür.
import UIKit
class CustomView: UIView {
override func touchesBegan(
_ touches: Set<UITouch>,
with event: UIEvent?
) {
// Toxunuş bu görünüş səviyyəsində işlənildi
print("CustomView toxunuşu işlədi")
// Hadisəni zəncir boyunca ötür
super.touchesBegan(touches, with: event)
}
}
Əsas xüsusiyyət ondan ibarətdir ki, super.touchesBegan çağırılması məcburi deyil. Əgər çağırılmazsa, hadisə yalnız cari səviyyədə emal ediləcək və Responder Chain boyunca daha da getməyəcək. Bu, tərtibatçıya emalda hansı obyektlərin iştirak etdiyi üzərində tam nəzarət verir.
Obyekt hadisəni aldıqda, lakin onu emal etmədikdə (metodu əvəz etmədikdə), iOS avtomatik olaraq hadisəni növbəti responder obyektinə next xassəsi vasitəsilə ötürür. Bu xassə Responder Chain adlanan tək istiqamətli siyahı yaradır.
UIViewController öz view-i ilə UIWindow arasında yerləşir: view hadisəni emal etməzsə, nəzarətçi bunu etmək şansı əldə edir. Bu, xüsusilə müştərək məntiq üçün faydalıdır — məsələn, istifadəçinin barmağının altında hansı view olmasından asılı olmayaraq bütün səhnədə işləməli olan jestin emalı.
Hit-Testing iOS-un toxunma nöqtəsi altında hansı view-in olduğunu müəyyən etdiyi prosesdir. hitTest:withEvent: metodu view iyerarxiyasını UIWindow-dan aşağıya doğru gəzir, uşaq view-lərdən hansının toxunma nöqtəsini ehtiva etdiyini və gizlədilmədiyini yoxlayır.
Alqoritm rekursiv işləyir: hər səviyyə üçün iOS view-ləri əlavə edilmənin tərs qaydasında yoxlayır (əvvəlcə yuxarıdakılar). View gizlədilməyibsə, şəffaf deyilsə və nöqtə onun bounds daxilindədirsə, onun bütün subviews üçün hitTest rekursiv olaraq işə salınır. Bütün şərtlərə cavab verən ən dərin view hit-test view — Responder Chain-də ilk obyekt olur.
override func hitTest(
_ point: CGPoint,
with event: UIEvent?
) -> UIView? {
if isUserInteractionEnabled &&
isHidden == false &&
alpha > 0.01 &&
point(inside: point, with: event) {
return super.hitTest(point, with: event)
}
return nil
}
Tərtibatçılar standart davranışı dəyişdirmək üçün hitTest-i əvəz edə bilərlər. Məsələn, kiçik bir düzmə üçün toxunma sahəsini genişləndirmək və ya hadisəni fiziki olaraq barmağın altında olmayan başqa view-ə yönləndirmək. Bu, xüsusi interaktiv elementlər yaratmaq üçün güclü bir vasitədir.
UIResponder iOS-da hadisələri emal edə bilən bütün obyektlər üçün baza sinifidir. UIView, UIViewController, UIApplication və UIWindow UIResponder-dən miras alır. Sinif müxtəlif hadisə növlərini emal etmək üçün əvəz edilə bilən metodlar dəsti təmin edir.
Əsas metod qruplarına toxunmalar üçün touchesBegan, touchesMoved, touchesEnded, touchesCancelled; fiziki düzmələr üçün pressesBegan, pressesEnded; və akselerometr hadisələri üçün motionBegan, motionEnded daxildir. Hər bir metod UITouch və ya UIPress obyektləri dəsti və hadisə haqqında əlavə metadata ehtiva edən UIEvent-ə istinad alır.
| UIResponder metodu | Təyinat |
|---|---|
| touchesBegan | Toxunma başladıqda çağırılır |
| touchesMoved | Barmaq hərəkət etdikdə çağırılır |
| touchesEnded | Barmaq buraxıldıqda çağırılır |
| touchesCancelled | Kəsilmə zamanı çağırılır (zəng, pərdənin sürüşdürülməsi) |
| pressesBegan | Fiziki düzmə basıldıqda çağırılır |
Anlamaq vacibdir ki, iOS bu metodları yalnız first responder və zəncirdəki sonrakı obyektlər üçün çağırır. Heç bir obyekt metodu əvəz etməyibsə, hadisə səhv yaratmır — sadəcə nəzərə alınmır. Hadisə emalını debug etmək üçün UIResponder touchEvent-də Symbolic Breakpoint istifadə edin.
Standart UIKit komponentləri işləri üçün Responder Chain-dən fəal şəkildə istifadə edir. UITextField fokus aldıqda first responder olur, bu da avtomatik olaraq klaviaturanı açır. UIButton toxunmaları özü də responder chain-ə əsaslanan UIControl mexanizmi vasitəsilə emal edir.
UITableView və UICollectionView hücrə seçimi və sürüşdürmə jestlərini emal etmək üçün responder zəncirindən istifadə edir. İstifadəçi hücrəyə toxunarsa, hadisəni əvvəlcə hücrənin özü, sonra UITableView, və yalnız bundan sonra UIViewController alır. UIGestureRecognizer touchesBegan-dən daha yüksək prioritetə malikdir — view-ə jest tanıyıcı əlavə edilərsə, o, hadisəni ilk olaraq alacaq.
Apple-a görə, Responder Chain-dən düzgün istifadə tətbiqin çatışanlığı üçün kritik əhəmiyyət kəsb edir. VoiceOver və digər köməkçi texnologiyalar interfeys elementləri arasında naviqasiya üçün responder zəncirindən istifadə edir. Zəncir qırılarsa, məhdud imkanlı istifadəçilər tətbiqlə qarşılıqlı əlaqə saxlaya bilməyəcək.
UIMenuController kontekst menyusunu göstərmək üçün də Responder Chain-dən istifadə edir. İstifadəçi menyunu çağırdıqda, sistem canPerformAction metodlarını və müvafiq aksiyon metodlarını tətbiq edən first responder axtarır. Menyu yalnız cari responder-in dəstəklədiyi aksiyalar üçün göstərilir.
Bu, məsələn, Kəs, Köçür, Yapışdır əmrlərini yalnız UITextField fokusda olduqda göstərməyə və UILabel ilə işlərkən onları gizlətməyə imkan verir. Tərtibatçı UIResponder alt sinfində onları tətbiq edərək və canPerformAction-dan true qaytararaq kontekst menyusuna xüsusi aksiyalar əlavə edə bilər.
Xüsusi responder obyekti yaratmaq tərtibatçıya hadisə emalı üzərində tam nəzarət verir. Bunun üçün UIResponder (və ya UIView/UIViewController) alt sinfi yaratmalı və lazımi hadisə emalı metodlarını əvəz etməlisiniz.
Çox vaxt xüsusi responder obyektləri standart UIGestureRecognizer ilə əhatə olunmayan xüsusi jestləri emal etmək üçün istifadə olunur. Məsələn, formaların çəkilməsinin tanınması, mürəkkəb multi-touch kombinasiyaları və ya xüsusi giriş nümunələri. Xüsusi responder bir neçə barmaqdan hadisələri toplayıb onların kombinasiyasına əsaslanaraq qərar qəbul edə bilər.
class DrawingResponder: UIResponder {
private var activeTouches: [UITouch: CGPoint] = [:]
override func touchesBegan(
_ touches: Set<UITouch>,
with event: UIEvent?
) {
for touch in touches {
activeTouches[touch] = touch.location(in: self)
}
}
override func touchesMoved(
_ touches: Set<UITouch>,
with event: UIEvent?
) {
for touch in touches {
let currentPoint = touch.location(in: self)
activeTouches[touch] = currentPoint
drawLine(from: activeTouches[touch]!, to: currentPoint)
}
}
}
Xüsusi responder yaradarkən next zəncirini düzgün konfiqurasiya etmək vacibdir. Obyektiniz standart UIKit iyerarxiyasının bir hissəsi deyilsə, onun next responder-inin hansı obyekt olacağını açıqça göstərməlisiniz. Bu, emal edilməmiş hadisələrin Responder Chain boyunca hərəkətini davam etdirəcəyini təmin edir.
Tez-tez verilən suallar
Responder Chain iOS-un toxunma, basılma və jest hadisələrini ardıcıl olaraq ötürdüyü UIResponder obyektlərinin iyerarxik zənciridir. Obyekt hadisəni emal etməzsə, o, UIApplication-a qədər zəncir boyunca növbəti responder obyektinə ötürülür.
Sıranı UIResponder obyektinizin next xassəsini əvəz etməklə dəyişdirmək olar. Standart yerinə başqa bir obyekt qaytarmaqla, emal edilməmiş hadisələri ona yönləndirirsiniz. Bu, qeyri-standart iyerarxiyalar üçün faydalıdır, məsələn, xüsusi konteyner bir neçə uşaq nəzarətçisini idarə etdikdə.
Hit-Testing toxunma nöqtəsi altında hansı view-in olduğunu müəyyən edir (ilkin alıcı), Responder Chain isə hadisənin hit-testdən sonra obyektlər arasında necə ötürüldüyünü müəyyən edir. Hit-test ilk obyekti tapır, responder chain bu obyekt hadisəni emal etməzsə, sonrakı marşrutlaşdırmanı təmin edir.
Zəncir kəsmək üçün, UIResponder-də hadisəni emal edin və super-i çağırmayın. Məsələn, touchesBegan-ı əvəz edib super.touchesBegan-ı çağırmamaqla, hadisənin daha da ötürülməsinin qarşısını alırsınız. Hadisə cari səviyyədə emal ediləcək və zəncirin növbəti halqalarına çatmayacaq.
Ən tez-tez rast gəlinən səbəblər: isUserInteractionEnabled false olaraq təyin edilib, view gizlədilib (isHidden = true), alpha 0.01-dən kiçikdir və ya view ana konteynerin hüdudlarından kənardadır. Həmçinin view və ya onun superview-də hadisələri touchesBegan-dən əvvəl tutan UIGestureRecognizer olub-olmadığını yoxlayın.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun