Önemli Noktalar
UIGestureRecognizer, jest tanıma sürecini ayrı nesnelere ayıran UIKit'teki soyut bir temel sınıftır. Her alt sınıf bir jest türünü işler: UITapGestureRecognizer belirli sayıda dokunma ile bir dokunmayı işler, UISwipeGestureRecognizer belirli bir yöndeki kaydırmayı işler. Geliştirici, addGestureRecognizer(:) yöntemi aracılığıyla UIView'e tanıyıcıyı ekler ve UIKit otomatik olarak dokunmaları izler, durumu günceller ve tanıma üzerine bir eylem çağırır.
UIGestureRecognizer'dan (iOS 3.2, 2010) önce, geliştiriciler UIResponder yöntemlerini — touchesBegan, touchesMoved, touchesEnded — geçersiz kılar ve dokunma yörüngelerini manuel olarak analiz ederdi. Bu, kod tekrarına ve eşzamanlı dokunmaları işlerken hatalara yol açardı. Apple bu mantığı UIGestureRecognizer'da kapsülleyerek çoklu dokunma, jest iptali ve aynı görünümde birden çok tanıyıcının eşzamanlı çalışması desteğini ekledi.
WWDC oturumlarına göre, Gesture Recognizer iPad'de 11 eşzamanlı dokunmaya, iPhone'da 5'e kadar işlem yapabilir. IT Sectr'de, tüm UIKit projelerinde kullanıcı girişini işlemenin standart yolu olarak UIGestureRecognizer'ı kullanıyoruz — bu, manuel touchesBegan izlemeyle ilişkili hataları ortadan kaldırdı.
Her UIGestureRecognizer 7 olası durumdan geçer, UIGestureRecognizer.State enum'unda tanımlanmıştır. Bu durumlar, tanıma yaşam döngüsünü yansıtır: dokunma algılamadan tamamlama veya iptale kadar. Durumları anlamak, özel tanıyıcılar uygulamak ve çakışmaları hata ayıklamak için kritiktir.
| Durum | Anlamı | Ne Zaman Oluşur |
|---|---|---|
| .possible | Başlangıç durumu, jest henüz tanınmadı | Bir görünüme eklendikten hemen sonra |
| .began | Jest tanındı ve yürütülmeye başladı | pan/longPress için ilk parmak hareketinde |
| .changed | Jest parametreleri değişti (koordinatlar, açı) | Her parmak hareketinde |
| .ended | Kullanıcı parmağını kaldırdı, jest tamamlandı | touchesEnded'da |
| .cancelled | Sistem tarafından jest kesintiye uğratıldı (gelen arama, yön değişikliği) | touchesCancelled'da |
| .failed | Koşullara göre jest tanınmadı | Tanıma olmadan touchesCancelled'da |
| .recognized | .ended ile eşanlamlı; jest başarıyla tanındı | .ended ile aynı |
Ayrık jestler (tap, swipe) .possible'dan doğrudan .ended veya .failed'a geçer. Sürekli jestler (pan, pinch, rotation, longPress) .possible → .began → .changed (tekrarlanan) → .ended'den geçer. Eylem yönteminde gestureRecognizer.state'i kontrol edin — bu, bir jestin başlangıcını, değişimini ve sonunu ayırt etmeyi sağlar.
UIKit, 7 yerleşik UIGestureRecognizer alt sınıfı sağlar, çoğu etkileşim senaryosunu kapsar. Her alt sınıfın belirli ayarları vardır: dokunma için numberOfTapsRequired, kaydırma için direction, uzun basma için minimumPressDuration.
Özel jestler için (örneğin, zikzak çizme), touchesBegan, touchesMoved, touchesEnded'ı geçersiz kılan ve durumu güncelleyen bir UIGestureRecognizer alt sınıfı oluşturulur. Apple, mümkün olduğunda yerleşik sınıfların kullanılmasını önerir — bunlar optimize edilmiştir ve birbirleriyle doğru şekilde etkileşime girer.
Aynı UIView üzerinde birden çok UIGestureRecognizer kullanıldığında (örneğin, dokunma ve çift dokunma), bir tanıma çakışması oluşur: çift dokunmada, tek dokunma önce tetiklenir. Apple, bir jestin tanınmasını diğeri başarısız olana kadar geciktirmek için require(toFail:) yöntemini sağlar.
Mekanizma şöyle çalışır: tapRecognizer.require(toFail: doubleTapRecognizer) çağrısı yaparak, tapRecognizer'ın yalnızca doubleTapRecognizer .failed ile sonuçlandıktan sonra .recognized durumuna geçeceğini belirtirsiniz. Bu, tek dokunmayı yürütmeden önce ~0,3 saniyelik bir gecikme ekler — kullanıcı iki kez dokunur ve ilk dokunma yok sayılır. Alternatif bir yaklaşım, eşzamanlı tanımaya izin veren gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) yöntemine sahip UIGestureRecognizerDelegate delegesidir (örneğin, bir harita için pan + pinch).
WWDC 2020'ye göre, UIKit uygulamalarındaki hataların yaklaşık %15'i jest çakışmalarının yanlış yapılandırılmasıyla ilgilidir. IT Sectr'de yaklaşımı standartlaştırdık: her ekranın require(toFail:) önceliklerine sahip bir jest şeması vardır — bu, çift dokunma tetikleme hatalarını tamamen ortadan kaldırdı.
UIImageView'a tek dokunma işleyicisi ekler. Dokunulduğunda, görüntünün opaklığı değişir — bir jestin bir görünüme bağlanmasını gösteren basit bir örnek.
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
}
}
}
Önemli nokta: UIImageView'da isUserInteractionEnabled varsayılan olarak false'dur — bu işaret olmadan, Gesture Recognizer dokunmaları almaz. UIView ve UIButton için bu işaret varsayılan olarak etkindir. Eylem yöntemi bir UITapGestureRecognizer parametresi alır ve bu parametre aracılığıyla dokunma koordinatlarını belirlemek için location(in:) alınabilir.
Önceki ekrana dönmek için sola kaydırmayı uygular. Yön yapılandırmasını ve jestin denetleyicinin kök görünümüne bağlanmasını gösterir.
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 ayrık bir jesttir: tanımadan hemen sonra .recognized'a geçer, arada .changed durumu olmaz. Bu nedenle, eylemde durumu kontrol etmek gerekmez — jest ya tanınır (eylem tetiklenir) ya da tanınmaz. direction özelliği dört değerden birini kabul eder: .left, .right, .up, .down. Birden çok yönü desteklemek için her biri için ayrı tanıyıcılar oluşturun.
Çakışma olmadan aynı görünümde tek ve çift dokunmanın nasıl yapılandırılacağını gösterir. Çift dokunma tanıyıcısı önceliğe sahiptir — tek dokunma yalnızca çift dokunma tanınmazsa tetiklenir.
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:) olmadan, çift dokunmada önce handleSingleTap tetiklenir, sonra handleDoubleTap — bu UX'i bozar. require(toFail:) ile tek dokunma, ikinci bir dokunmanın gelmediğinden emin olmak için ~0,3 saniye bekler. IT Sectr'de bu desen, çift dokunmanın yakınlaştırdığı ve tek dokunmanın bir öğeyi seçtiği görüntü düzenleyicilerde ve galerilerde kullanılır.
Sıkça Sorulan Sorular
Evet, UIView aynı anda birden çok UIGestureRecognizer örneğini destekler. Çakışmaları çözmek için, tanıma sırasını belirleyen require(toFail:) yöntemini kullanın. Paralel jest işlemi için (örneğin, bir haritada pan + pinch), true döndüren gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) temsilci yöntemini uygulayın.
UIGestureRecognizer, dokunma desenlerini otomatik olarak tanıyan ve durumları yöneten üst düzey bir soyutlamadır. touchesBegan, manuel koordinat izleme, zamanlama ve dokunma iptali gerektiren düşük seviyeli bir UIResponder yöntemidir. Gesture Recognizer daha basit, daha güvenilir ve standart jestler için tercih edilir; touchesBegan yalnızca özel grafikler için haklı çıkar.
Yerel SwiftUI değiştiriciler kullanır: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture. Bunlar, SwiftUI hiyerarşisine entegre edilmiş UIGestureRecognizer'ın bildirimsel analoglarıdır. Gerekirse, UIViewRepresentable aracılığıyla bir UIKit tanıyıcı sarılabilir, ancak Apple yerel SwiftUI jestlerini kullanmayı önerir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun