Asosiy fikrlar
UIGestureRecognizer — UIKit-dagi abstrakt asosiy sinf bo'lib, jestni tanib olish jarayonini alohida obyektlarga ajratadi. Har bir pastki sinf bir jest turiga javob beradi: UITapGestureRecognizer — ma'lum miqdordagi barmoqlar bilan tap uchun, UISwipeGestureRecognizer — berilgan yo'nalishda surish uchun. Dasturchi UIView-ga addGestureRecognizer(:) metodi orqali tanib oluvchini qo'shadi va UIKit avtomatik ravishda teginishlarni kuzatadi, holatni yangilaydi va tanib olinganda aksiyani chaqiradi.
UIGestureRecognizer (iOS 3.2, 2010) paydo bo'lishidan oldin dasturchilar UIResponder metodlarini — touchesBegan, touchesMoved, touchesEnded — bekor qilar va teginish traektoriyasini qo'lda tahlil qilishardi. Bu kodning takrorlanishiga va bir vaqtda teginishlarni qayta ishlashda xatolarga olib kelardi. Apple ushbu mantiqni UIGestureRecognizer-ga inkapsulyatsiya qilib, multitouch, jestlarni bekor qilish va bir ko'rinishda bir nechta tanib oluvchilarning bir vaqtda ishlashini qo'llab-quvvatladi.
WWDC sessiyalariga ko'ra, Gesture Recognizer iPad-da 11 ta bir vaqtda teginish va iPhone-da 5 ta teginishni qayta ishlaydi. IT Sectr-da UIGestureRecognizer-ni barcha UIKit loyihalarida foydalanuvchi kiritishini qayta ishlashning standart usuli sifatida ishlatamiz — bu touchesBegan bilan qo'lda kuzatish bilan bog'liq xatolarni bartaraf etdi.
Har bir UIGestureRecognizer UIGestureRecognizer.State enumida belgilangan 7 mumkin bo'lgan holatdan o'tadi. Bu holatlar tanib olish hayotiy siklini aks ettiradi: teginishni aniqlashdan jestning tugashiga yoki bekor qilinishigacha. Holatlarni tushunish maxsus tanib oluvchilarni amalga oshirish va ziddiyatlarni tuzatish uchun muhimdir.
| Holat | Ma'nosi | Qachon paydo bo'ladi |
|---|---|---|
| .possible | Boshlang'ich holat, jest hali tanib olinmagan | Ko'rinishga qo'shilgandan so'ng darhol |
| .began | Jest tanib olindi va bajarila boshlandi | Pan/longPress uchun barmoqning birinchi harakatida |
| .changed | Jest parametrlari o'zgardi (koordinatalar, burchak) | Har bir barmoq harakatida |
| .ended | Foydalanuvchi barmog'ini oldi, jest tugadi | touchesEnded da |
| .cancelled | Jest tizim tomonidan to'xtatildi (qo'ng'iroq, orientatsiya o'zgarishi) | touchesCancelled da |
| .failed | Jest shartlarga ko'ra tanib olinmadi | Tanib olinmasdan touchesCancelled da |
| .recognized | .ended bilan sinonim; jest muvaffaqiyatli tanib olindi | .ended bilan bir xil |
Diskret jestlar (tap, swipe) .possible dan to'g'ridan-to'g'ri .ended yoki .failed ga o'tadi. Uzluksiz jestlar (pan, pinch, rotation, longPress) .possible → .began → .changed (ko'p marta) → .ended dan o'tadi. Aksiya metodida gestureRecognizer.state ni tekshiring — bu jestning boshlanishi, o'zgarishi va tugashini farqlash imkonini beradi.
UIKit UIGestureRecognizer ning 7 ta o'rnatilgan pastki sinfini taqdim etadi, aksariyat o'zaro ta'sir stsenariylarini qamrab oladi. Har bir pastki sinfning o'ziga xos sozlamalari bor: numberOfTapsRequired tap uchun, direction surish uchun, minimumPressDuration uzoq bosish uchun.
Maxsus jestlar uchun (masalan, zigzag chizish) UIGestureRecognizer pastki sinfi touchesBegan, touchesMoved, touchesEnded metodlarini bekor qilish va state ni yangilash orqali yaratiladi. Apple iloji boricha o'rnatilgan sinflardan foydalanishni tavsiya qiladi — ular optimallashtirilgan va bir-biri bilan to'g'ri o'zaro aloqada bo'ladi.
Bir UIView da bir nechta UIGestureRecognizer ishlatilganda (masalan, tap va double-tap), tanib olish ziddiyati yuzaga keladi: ikki marta bosganda avval yakka tap ishga tushadi. Yechim uchun Apple require(toFail:) metodini taqdim etadi, u bir jestning tanib olinishini ikkinchisi muvaffaqiyatsiz tugaguncha kechiktiradi.
Mexanizm shunday ishlaydi: tapRecognizer.require(toFail: doubleTapRecognizer) ni chaqirish orqali tapRecogniser .recognized holatiga faqat doubleTapRecogniser .failed bilan tugagandan keyin o'tishini belgilaysiz. Bu yakka tap bajarilishidan oldin ~0.3 soniya kechikish qo'shadi — foydalanuvchi ikki marta bosadi va birinchi tap e'tiborga olinmaydi. Muqobil usul — gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) metodi bilan UIGestureRecognizerDelegate, bir vaqtda tanib olishga ruxsat beradi (masalan, xarita uchun pan + pinch).
WWDC 2020 ma'lumotlariga ko'ra, UIKit ilovalaridagi xatolarning taxminan 15% i jest ziddiyatlarining noto'g'ri sozlanishi bilan bog'liq. IT Sectr-da yondashuvni standartlashtirdik: har bir ekran uchun require(toFail:) ustuvorliklari ko'rsatilgan jest sxemasi yaratiladi — bu taplarning ikki marta ishga tushishi bilan bog'liq xatolarni butunlay bartaraf etdi.
UIImageView-ga yakka tap ishlovchisini qo'shadi. Tap paytida rasm shaffofligini o'zgartiradi — jestning ko'rinishga bog'lanishini ko'rsatadigan eng sodda misol.
import UIKit
class ImageViewController: UIViewController {
@IBOutlet private var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(
target: self,
action: #selector(handleTap(_:))
)
tap.numberOfTapsRequired = 1
imageView.addGestureRecognizer(tap)
imageView.isUserInteractionEnabled = true
}
@objc private func handleTap(_: UITapGestureRecognizer) {
UIView.animate(withDuration: 0.2) {
self.imageView.alpha = self.imageView.alpha == 1.0 ? 0.5 : 1.0
}
}
}
Asosiy nuqta: UIImageView da isUserInteractionEnabled standart bo'yicha false — bu bayroqsiz Gesture Recognizer teginishlarni qabul qilmaydi. UIView va UIButton uchun bayroq standart bo'yicha yoqilgan. Aksiya metodi UITapGestureRecognizer parametrini qabul qiladi, uning orqali tap koordinatalarini aniqlash uchun location(in:) olish mumkin.
Oldingi ekranga qaytish uchun chapga surishni amalga oshiradi. Yo'nalishni sozlash va jestning ildiz ko'rinishiga bog'lanishini namoyish etadi.
import UIKit
class DetailViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let swipeLeft = UISwipeGestureRecognizer(
target: self,
action: #selector(handleSwipe(_:))
)
swipeLeft.direction = .left
view.addGestureRecognizer(swipeLeft)
}
@objc private func handleSwipe(_: UISwipeGestureRecognizer) {
navigationController?.popViewController(animated: true)
}
}
UISwipeGestureRecognizer — diskret jest: tanib olingandan so'ng darhol .recognised holatiga o'tadi, oraliq .changed holda. Shuning uchun aksiyada state ni tekshirish shart emas — jest yoki tanib olinadi (aksiya chaqiriladi) yoki yo'q. direction xususiyati to'rt qiymatdan birini qabul qiladi: .left, .right, .up, .down. Bir nechta yo'nalishlarni qo'llab-quvvatlash uchun har biri uchun alohida tanib oluvchi yarating.
Bir ko'rinishda ziddiyatsiz yakka va ikki marta tapni qanday sozlashni ko'rsatadi. Ikki marta tap tanib oluvchisi ustuvorlikka ega — yakka tap faqat ikki marta tap tanib olinmasa ishga tushadi.
import UIKit
class TapViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let singleTap = UITapGestureRecognizer(
target: self,
action: #selector(handleSingleTap)
)
singleTap.numberOfTapsRequired = 1
let doubleTap = UITapGestureRecognizer(
target: self,
action: #selector(handleDoubleTap)
)
doubleTap.numberOfTapsRequired = 2
singleTap.require(toFail: doubleTap)
view.addGestureRecognizer(singleTap)
view.addGestureRecognizer(doubleTap)
}
@objc private func handleSingleTap() {
print("Single tap — after 0.3s delay")
}
@objc private func handleDoubleTap() {
print("Double tap — instant")
}
}
require(toFail:) bo'lmasa, ikki marta bosganda avval handleSingleTap, keyin handleDoubleTap chaqiriladi — bu UX ni buzadi. require(toFail:) bilan yakka tap ~0.3 soniya kutadi, ikkinchi tap kelmasligiga ishonch hosil qilish uchun. IT Sectr-da bu namuna rasm muharrirlari va galereyalarda qo'llaniladi, bu yerda ikki marta tap yaqinlashtiradi, yakka tap esa elementni tanlaydi.
Ko'p beriladigan savollar
Ha, UIView bir vaqtda bir nechta UIGestureRecognizer ni qo'llab-quvvatlaydi. Ziddiyatlarni hal qilish uchun tanib olish tartibini belgilovchi require(toFail:) metodidan foydalaning. Jestlarning parallel ishlashi uchun (masalan, xaritada pan + pinch) true qaytaruvchi gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) delegatini amalga oshiring.
UIGestureRecognizer — teginish naqshlarini avtomatik taniydigan va holatlarni boshqaradigan yuqori darajali abstraksiya. touchesBegan — koordinatalar, vaqt va teginishlarni bekor qilishni qo'lda kuzatishni talab qiluvchi UIResponder ning past darajali metodi. Gesture Recognizer soddaroq, ishonchliroq va standart jestlar uchun afzal; touchesBegan faqat maxsus grafika uchun oqlanadi.
Mahalliy SwiftUI da modifikatorlardan foydalaniladi: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture. Bular SwiftUI ierarxiyasiga integratsiyalashgan UIGestureRecognizer ning deklarativ analoglari. Zarur bo'lsa, UIKit tanib oluvchisini UIViewRepresentable orqali o'rashingiz mumkin, ammo Apple mahalliy SwiftUI jestlaridan foydalanishni tavsiya qiladi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.