Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Объявление обработчиков жестов в iOS разработке
В iOS существует несколько основных способов объявления обработчиков жестов, каждый из которых подходит для разных сценариев. Рассмотрим основные подходы.
1. Target-Action с использованием addGestureRecognizer
Наиболее распространенный способ — программное создание UIGestureRecognizer и добавление его к представлению с указанием метода-обработчика.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Создаем жестовый распознаватель
let tapGesture = UITapGestureRecognizer(
target: self,
action: #selector(handleTap(_:))
)
// Настраиваем параметры (опционально)
tapGesture.numberOfTapsRequired = 1
tapGesture.numberOfTouchesRequired = 1
// Добавляем распознаватель к представлению
view.addGestureRecognizer(tapGesture)
// Пример с несколькими жестами
let pinchGesture = UIPinchGestureRecognizer(
target: self,
action: #selector(handlePinch(_:))
)
view.addGestureRecognizer(pinchGesture)
}
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
let location = gesture.location(in: view)
print("Тап распознан в точке: \(location)")
// Дополнительная логика обработки
if gesture.state == .ended {
// Выполняем действия при завершении жеста
}
}
@objc private func handlePinch(_ gesture: UIPinchGestureRecognizer) {
let scale = gesture.scale
print("Масштабирование: \(scale)")
}
}
2. Использование UIGestureRecognizerDelegate
Для более сложной логики взаимодействия с жестами используется протокол UIGestureRecognizerDelegate.
class GestureViewController: UIViewController, UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let panGesture = UIPanGestureRecognizer(
target: self,
action: #selector(handlePan(_:))
)
panGesture.delegate = self
view.addGestureRecognizer(panGesture)
let swipeGesture = UISwipeGestureRecognizer(
target: self,
action: #selector(handleSwipe(_:))
)
swipeGesture.direction = [.left, .right]
swipeGesture.delegate = self
view.addGestureRecognizer(swipeGesture)
}
// Делегатный метод для одновременной обработки жестов
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// Разрешаем одновременную работу pan и swipe жестов
return true
}
// Делегатный метод для требования других жестов к провалу
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// Настраиваем приоритеты жестов
return false
}
}
3. IBOutlets и Interface Builder
Визуальное создание жестов через Storyboard/XIB с подключением через @IBAction.
class StoryboardViewController: UIViewController {
// 1. Перетащите Gesture Recognizer из библиотеки объектов на представление в Storyboard
// 2. Создайте IBAction связь
@IBAction func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
switch gesture.state {
case .began:
print("Долгое нажатие начато")
case .changed:
let location = gesture.location(in: view)
print("Изменение позиции: \(location)")
case .ended:
print("Долгое нажатие завершено")
default:
break
}
}
// Можно также создать IBOutlet для жеста
@IBOutlet weak var customGesture: UIRotationGestureRecognizer!
@IBAction func handleRotation(_ gesture: UIRotationGestureRecognizer) {
let rotation = gesture.rotation
print("Вращение: \(rotation) радиан")
}
}
4. Современный подход с UIGestureRecognizer closures (iOS 14+)
Начиная с iOS 14, появилась удобная возможность использовать замыкания.
class ModernViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let doubleTapGesture = UITapGestureRecognizer()
doubleTapGesture.numberOfTapsRequired = 2
// Использование замыкания для обработки
doubleTapGesture.addAction { [weak self] _ in
guard let self = self else { return }
self.handleDoubleTap()
}
view.addGestureRecognizer(doubleTapGesture)
// Альтернативный синтаксис с UIAction
let swipeAction = UIAction { [weak self] _ in
self?.handleSwipeAction()
}
let swipeGesture = UISwipeGestureRecognizer(
direction: .up,
primaryAction: swipeAction
)
view.addGestureRecognizer(swipeGesture)
}
private func handleDoubleTap() {
print("Двойной тап обработан через замыкание")
}
private func handleSwipeAction() {
print("Свайп обработан через UIAction")
}
}
5. Кастомные жесты через наследование
Создание собственных обработчиков жестов путем наследования от UIGestureRecognizer.
class CircleGestureRecognizer: UIGestureRecognizer {
private var points: [CGPoint] = []
private let tolerance: CGFloat = 20.0
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
points.removeAll()
if let touch = touches.first {
points.append(touch.location(in: view))
}
state = .began
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
if let touch = touches.first {
points.append(touch.location(in: view))
if isCircle() {
state = .ended
} else {
state = .changed
}
}
}
private func isCircle() -> Bool {
// Логика определения кругового жеста
return points.count > 10 // Упрощенная проверка
}
}
Ключевые рекомендации:
- Используйте
.stateжеста для обработки разных фаз (.began,.changed,.ended,.cancelled) - Учитывайте приоритеты жестов через методы делегата при наличии нескольких жестов
- Не забывайте про weak self в замыканиях для избежания циклов удержания
- Тестируйте на реальных устройствах, так как симулятор может не полностью эмулировать мультитач
- Оптимизируйте производительность при обработке жестов в реальном времени (например, при рисовании)
Выбор конкретного способа зависит от требований проекта: для простых случаев достаточно target-action, для сложной логики взаимодействия — делегаты, а для современного кода — замыкания.