Gesture Recognizer — τι είναι, επεξεργασία αφής στο iOS

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-27 Χρόνος ανάγνωσης: 8 λεπ
Gesture Recognizer — μια αφαίρεση στο UIKit που μετατρέπει μια ακολουθία αφών του χρήστη σε μια αναγνωρισμένη χειρονομία: tap, σύρσιμο, παρατεταμένο πάτημα, τσίμπημα ή περιστροφή. Αντί για μη αυτόματη παρακολούθηση συντεταγμένων στις μεθόδους touchesBegan/touchesMoved, ο προγραμματιστής προσθέτει ένα έτοιμο αντικείμενο UIGestureRecognizer στο UIView και υλοποιεί τη μέθοδο δράσης. Σύμφωνα με το Apple Developer Documentation, το UIGestureRecognizer υποστηρίζει 7 ενσωματωμένες υποκλάσεις που καλύπτουν το 95% των τυπικών χειρονομιών σε εφαρμογές για κινητά.

Κύρια σημεία

  • UIGestureRecognizer — αφηρημένη κλάση UIKit για αναγνώριση μοτίβων αφής: taps, συρσίματα, τσιμπήματα, περιστροφές και παρατεταμένα πατήματα.
  • 7 ενσωματωμένες υποκλάσεις: UITapGestureRecognizer, UISwipeGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UILongPressGestureRecognizer, UIPanGestureRecognizer, UIScreenEdgePanGestureRecognizer.
  • Κάθε αναγνωριστής έχει κατάσταση (possible, began, changed, ended, cancelled, failed) που ενημερώνεται καθώς κινούνται τα δάχτυλα.
  • Για την επίλυση συγκρούσεων μεταξύ χειρονομιών χρησιμοποιείται η μέθοδος require(toFail:), η οποία ορίζει την προτεραιότητα αναγνώρισης.
  • Το Gesture Recognizer λειτουργεί με UIKit και UIViewRepresentable στο SwiftUI, αλλά στο εγγενές SwiftUI εφαρμόζονται τροποποιητές χειρονομιών.

Τι είναι το Gesture Recognizer;

UIGestureRecognizer — μια αφηρημένη βασική κλάση στο UIKit που αποσυνθέτει τη διαδικασία αναγνώρισης χειρονομιών σε ξεχωριστά αντικείμενα. Κάθε υποκλάση είναι υπεύθυνη για έναν τύπο χειρονομίας: UITapGestureRecognizer — για tap με συγκεκριμένο αριθμό δαχτύλων, UISwipeGestureRecognizer — για σύρσιμο σε συγκεκριμένη κατεύθυνση. Ο προγραμματιστής προσθέτει τον αναγνωριστή στο UIView μέσω της μεθόδου addGestureRecognizer(:), και το UIKit παρακολουθεί αυτόματα τις αφές, ενημερώνει την κατάσταση και καλεί τη δράση κατά την αναγνώριση.

Πριν από την εμφάνιση του UIGestureRecognizer (iOS 3.2, 2010), οι προγραμματιστές παρακάμπτουν τις μεθόδους UIResponder — touchesBegan, touchesMoved, touchesEnded — και ανέλυαν χειροκίνητα την τροχιά των αφών. Αυτό οδηγούσε σε διπλασιασμό κώδικα και σφάλματα κατά την επεξεργασία ταυτόχρονων αφών. Η Apple ενσωμάτωσε αυτή τη λογική στο UIGestureRecognizer, προσθέτοντας υποστήριξη για multitouch, ακύρωση χειρονομιών και ταυτόχρονη λειτουργία πολλών αναγνωριστών σε μία προβολή.

Σύμφωνα με τις συνεδρίες WWDC, το Gesture Recognizer επεξεργάζεται έως 11 ταυτόχρονες αφές στο iPad και 5 στο iPhone. Στην IT Sectr, χρησιμοποιούμε το UIGestureRecognizer ως τον τυπικό τρόπο επεξεργασίας εισόδου χρήστη σε όλα τα έργα UIKit — αυτό εξάλειψε σφάλματα που σχετίζονται με τη μη αυτόματη παρακολούθηση του touchesBegan.

Καταστάσεις UIGestureRecognizer

Κάθε UIGestureRecognizer διέρχεται από 7 πιθανές καταστάσεις, που ορίζονται στο enum UIGestureRecognizer.State. Αυτές οι καταστάσεις αντικατοπτρίζουν τον κύκλο ζωής αναγνώρισης: από την ανίχνευση αφής έως την ολοκλήρωση ή ακύρωση της χειρονομίας. Η κατανόηση των καταστάσεων είναι κρίσιμη για την υλοποίηση προσαρμοσμένων αναγνωριστών και τον εντοπισμό σφαλμάτων συγκρούσεων.

Κατάσταση Σημασία Πότε προκύπτει
.possible Αρχική κατάσταση, η χειρονομία δεν έχει αναγνωριστεί ακόμα Αμέσως μετά την προσθήκη στην προβολή
.began Η χειρονομία αναγνωρίστηκε και άρχισε να εκτελείται Στην πρώτη κίνηση δαχτύλου για pan/longPress
.changed Οι παράμετροι της χειρονομίας άλλαξαν (συντεταγμένες, γωνία) Σε κάθε κίνηση δαχτύλου
.ended Ο χρήστης σήκωσε το δάχτυλο, η χειρονομία ολοκληρώθηκε Στο touchesEnded
.cancelled Η χειρονομία διακόπηκε από το σύστημα (εισερχόμενη κλήση, αλλαγή προσανατολισμού) Στο touchesCancelled
.failed Η χειρονομία δεν αναγνωρίστηκε σύμφωνα με τις συνθήκες Στο touchesCancelled χωρίς αναγνώριση
.recognized Συνώνυμο του .ended; η χειρονομία αναγνωρίστηκε επιτυχώς Ίδιο με το .ended

Οι διακριτές χειρονομίες (tap, swipe) μεταβαίνουν από .possible απευθείας σε .ended ή .failed. Οι συνεχείς χειρονομίες (pan, pinch, rotation, longPress) διέρχονται από .possible → .began → .changed (πολλαπλές φορές) → .ended. Στη μέθοδο δράσης, ελέγξτε το gestureRecognizer.state — αυτό επιτρέπει τη διάκριση της αρχής, της αλλαγής και του τέλους της χειρονομίας.

Τύποι χειρονομιών στο iOS

Το UIKit παρέχει 7 ενσωματωμένες υποκλάσεις του UIGestureRecognizer, που καλύπτουν τα περισσότερα σενάρια αλληλεπίδρασης. Κάθε υποκλάση έχει συγκεκριμένες ρυθμίσεις: numberOfTapsRequired για tap, direction για σύρσιμο, minimumPressDuration για παρατεταμένο πάτημα.

  • UITapGestureRecognizer — αναγνωρίζει μεμονωμένα και πολλαπλά taps. Ρυθμίζεται ο αριθμός αφών (numberOfTapsRequired) και δαχτύλων (numberOfTouchesRequired). Χρησιμοποιείται για κουμπιά, συνδέσμους, επιλογή στοιχείων.
  • UISwipeGestureRecognizer — αναγνωρίζει σύρσιμο σε μία από τις τέσσερις κατευθύνσεις (right, left, up, down). Η ιδιότητα direction ορίζει την κατεύθυνση· numberOfTouchesRequired — τον αριθμό δαχτύλων.
  • UIPanGestureRecognizer — συνεχής χειρονομία για μεταφορά. Η μέθοδος translation(in:) επιστρέφει μετατόπιση από το σημείο εκκίνησης. Χρησιμοποιείται για drag-and-drop, καρουζέλ, pull-to-refresh.
  • UIPinchGestureRecognizer — κλιμάκωση με δύο δάχτυλα. Η ιδιότητα scale αντικατοπτρίζει τον τρέχοντα παράγοντα κλίμακας. Αναλύεται λεπτομερώς στο άρθρο Pinch-to-Zoom.
  • UIRotationGestureRecognizer — περιστροφή με δύο δάχτυλα. Η ιδιότητα rotation αποθηκεύει τη γωνία σε ακτίνια. Χρησιμοποιείται για περιστροφή εικόνων, χαρτών, καμβάδων.
  • UILongPressGestureRecognizer — παρατεταμένο πάτημα. Παράμετροι minimumPressDuration (δευτερόλεπτα), allowableMovement (pixel). Χρησιμοποιείται για μενού περιβάλλοντος, μεταφορά στοιχείων.
  • UIScreenEdgePanGestureRecognizer — πανοραμική κίνηση από την άκρη της οθόνης. Η ιδιότητα edges καθορίζει ποια άκρη να παρακολουθεί. Χρησιμοποιείται για χειρονομίες πλοήγησης, κουρτίνες ειδοποιήσεων.

Για προσαρμοσμένες χειρονομίες (π.χ. σχεδίαση ζιγκ-ζαγκ) δημιουργείται υποκλάση του UIGestureRecognizer με παράκαμψη των μεθόδων touchesBegan, touchesMoved, touchesEnded και ενημέρωση κατάστασης. Η Apple συνιστά τη χρήση ενσωματωμένων κλάσεων όπου είναι δυνατόν — είναι βελτιστοποιημένες και αλληλεπιδρούν σωστά μεταξύ τους.

Επίλυση συγκρούσεων μεταξύ χειρονομιών

Όταν σε ένα UIView χρησιμοποιούνται πολλά UIGestureRecognizer (π.χ. tap και double-tap), προκύπτει σύγκρουση αναγνώρισης: στο διπλό tap, πρώτα ενεργοποιείται το μεμονωμένο tap. Για λύση, η Apple παρέχει τη μέθοδο require(toFail:), η οποία καθυστερεί την αναγνώριση μιας χειρονομίας έως ότου η άλλη αποτύχει.

Ο μηχανισμός λειτουργεί ως εξής: καλώντας το tapRecognizer.require(toFail: doubleTapRecognizer), ορίζετε ότι το tapRecogniser θα μεταβεί στην κατάσταση .recognized μόνο αφού το doubleTapRecogniser ολοκληρωθεί σε .failed. Αυτό προσθέτει καθυστέρηση ~0,3 δευτερολέπτου πριν από την εκτέλεση του μεμονωμένου tap — ο χρήστης πατά δύο φορές και το πρώτο tap αγνοείται. Εναλλακτική μέθοδος — ο εκπρόσωπος UIGestureRecognizerDelegate με τη μέθοδο gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), που επιτρέπει ταυτόχρονη αναγνώριση (π.χ. pan + pinch για χάρτη).

Σύμφωνα με το WWDC 2020, περίπου 15% των σφαλμάτων σε εφαρμογές UIKit σχετίζονται με εσφαλμένη ρύθμιση συγκρούσεων χειρονομιών. Στην IT Sectr, τυποποιήσαμε την προσέγγιση: για κάθε οθόνη δημιουργείται ένα σχήμα χειρονομιών με προτεραιότητες require(toFail:) — αυτό εξάλειψε εντελώς τα σφάλματα με διπλή ενεργοποίηση tap.

Παραδείγματα κώδικα σε Swift

Παράδειγμα 1: UITapGestureRecognizer — tap σε εικόνα

Προσθέτει έναν χειριστή μεμονωμένου tap στο UIImageView. Κατά το tap, η εικόνα αλλάζει διαφάνεια — το απλούστερο παράδειγμα που δείχνει τη σύνδεση της χειρονομίας με μια προβολή.

swift
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
        }
    }
}

Βασικό σημείο: το isUserInteractionEnabled στο UIImageView είναι από προεπιλογή false — χωρίς αυτή τη σημαία, το Gesture Recognizer δεν θα λαμβάνει αφές. Για UIView και UIButton, η σημαία είναι ενεργοποιημένη από προεπιλογή. Η μέθοδος δράσης δέχεται μια παράμετρο UITapGestureRecognizer μέσω της οποίας μπορεί να ληφθεί το location(in:) για τον προσδιορισμό των συντεταγμένων του tap.

Παράδειγμα 2: UISwipeGestureRecognizer — σύρσιμο για πλοήγηση

Υλοποιεί σύρσιμο προς τα αριστερά για επιστροφή στην προηγούμενη οθόνη. Δείχνει τη ρύθμιση κατεύθυνσης και τη σύνδεση της χειρονομίας στην προβολή ρίζας του ελεγκτή.

swift
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 — είναι μια διακριτή χειρονομία: μεταβαίνει σε .recognised αμέσως μετά την αναγνώριση, χωρίς ενδιάμεσο .changed. Επομένως, στη δράση δεν χρειάζεται να ελέγχεται η κατάσταση — η χειρονομία είτε αναγνωρίζεται (καλείται η δράση) είτε όχι. Η ιδιότητα direction δέχεται μία από τέσσερις τιμές: .left, .right, .up, .down. Για υποστήριξη πολλαπλών κατευθύνσεων, δημιουργήστε ξεχωριστούς αναγνωριστές για κάθε μία.

Παράδειγμα 3: Συνδυασμός χειρονομιών με require(toFail:)

Δείχνει πώς να ρυθμίσετε μεμονωμένο και διπλό tap στην ίδια προβολή χωρίς σύγκρουση. Ο αναγνωριστής διπλού tap έχει προτεραιότητα — το μεμονωμένο tap ενεργοποιείται μόνο εάν το διπλό tap δεν αναγνωριστεί.

swift
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:), στο διπλό tap, πρώτα θα κληθεί το handleSingleTap, μετά το handleDoubleTap — αυτό χαλάει την εμπειρία χρήστη. Με το require(toFail:), το μεμονωμένο tap περιμένει ~0,3 δευτερόλεπτα για να βεβαιωθεί ότι δεν θα ακολουθήσει δεύτερο tap. Στην IT Sectr, αυτό το μοτίβο χρησιμοποιείται σε επεξεργαστές εικόνων και γκαλερί, όπου το διπλό tap μεγεθύνει και το μεμονωμένο επιλέγει ένα στοιχείο.

Συχνές ερωτήσεις

Μπορούν να χρησιμοποιηθούν πολλαπλά Gesture Recognizer σε μία προβολή;

Ναι, το UIView υποστηρίζει πολλαπλά UIGestureRecognizer ταυτόχρονα. Για την επίλυση συγκρούσεων, χρησιμοποιήστε τη μέθοδο require(toFail:), η οποία καθορίζει τη σειρά αναγνώρισης. Για παράλληλη λειτουργία χειρονομιών (π.χ. pan + pinch σε χάρτη) υλοποιήστε τον εκπρόσωπο gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), που επιστρέφει true.

Σε τι διαφέρει το UIGestureRecognizer από το touchesBegan;

UIGestureRecognizer — αφαίρεση υψηλού επιπέδου που αναγνωρίζει αυτόματα μοτίβα αφής και διαχειρίζεται καταστάσεις. Το touchesBegan — μέθοδος χαμηλού επιπέδου του UIResponder που απαιτεί μη αυτόματη παρακολούθηση συντεταγμένων, χρονισμού και ακύρωσης αφών. Το Gesture Recognizer είναι απλούστερο, αξιόπιστο και προτιμότερο για τυπικές χειρονομίες· το touchesBegan δικαιολογείται μόνο για προσαρμοσμένα γραφικά.

Λειτουργεί το Gesture Recognizer στο SwiftUI;

Στο εγγενές SwiftUI, χρησιμοποιούνται τροποποιητές: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture. Αυτά είναι δηλωτικά ανάλογα του UIGestureRecognizer, ενσωματωμένα στην ιεραρχία SwiftUI. Εάν χρειαστεί, μπορείτε να τυλίξετε έναν αναγνωριστή UIKit μέσω UIViewRepresentable, αλλά η Apple συνιστά τη χρήση εγγενών χειρονομιών SwiftUI.

Σύνοψη

  • UIGestureRecognizer — αφαίρεση UIKit για αποσύνθεση της λογικής αναγνώρισης χειρονομιών σε ξεχωριστά αντικείμενα με αυτόματη διαχείριση καταστάσεων.
  • 7 ενσωματωμένες υποκλάσεις καλύπτουν το 95% των τυπικών χειρονομιών: tap, σύρσιμο, πανοραμική κίνηση, τσίμπημα, περιστροφή, παρατεταμένο πάτημα και σύρσιμο από άκρη.
  • Κάθε αναγνωριστής διέρχεται από 7 καταστάσεις — από .possible έως .ended/.failed, επιτρέποντας ακριβή παρακολούθηση διακριτών και συνεχών χειρονομιών.
  • Η μέθοδος require(toFail:) επιλύει συγκρούσεις μεταξύ χειρονομιών στην ίδια προβολή, ορίζοντας προτεραιότητα αναγνώρισης.
  • Στο SwiftUI χρησιμοποιούνται δηλωτικοί τροποποιητές χειρονομιών, αλλά οι αναγνωριστές UIKit είναι προσβάσιμοι μέσω UIViewRepresentable.
  • Το Gesture Recognizer είναι υποχρεωτικό για έργα UIKit· το touchesBegan δικαιολογείται μόνο για προσαρμοσμένη σχεδίαση και γραφικά χαμηλού επιπέδου.
  • Χρησιμοποιήστε require(toFail:) για ζεύγη tap/double-tap και gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) για παράλληλες χειρονομίες.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης