Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
UIGestureRecognizer: распознаватель жестов в iOS
UIGestureRecognizer — это абстрактный базовый класс в iOS фреймворке UIKit, который предоставляет механизм для распознавания и обработки различных типов жестов пользователя (тапов, свайпов, масштабирования и т.д.) на представлениях (UIView). Он инкапсулирует логику детектирования сложных паттернов касаний, преобразуя низкоуровневые события UITouch в высокоуровневые семантические жесты, что значительно упрощает разработку интерактивных интерфейсов.
Основные типы жестов (подклассы)
iOS предоставляет несколько конкретных подклассов для распознавания стандартных жестов:
-
UITapGestureRecognizer: Распознает один или несколько быстрых касаний.
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:))) tapGesture.numberOfTapsRequired = 1 imageView.addGestureRecognizer(tapGesture) imageView.isUserInteractionEnabled = true // Важно! -
UIPinchGestureRecognizer: Распознает "пинч" (сведение и разведение двух пальцев), обычно для масштабирования.
-
UIRotationGestureRecognizer: Распознает вращение двумя пальцами.
-
UISwipeGestureRecognizer: Распознает быстрые свайпы в одном из четырех направлений.
-
UIPanGestureRecognizer: Распознает непрерывное перетаскивание (пан).
-
UIScreenEdgePanGestureRecognizer: Подкласс UIPanGestureRecognizer, распознающий пан от края экрана (часто используется для навигации).
-
UILongPressGestureRecognizer: Распознает долгое нажатие.
Ключевые принципы работы и API
-
Прикрепление к представлению: Каждый распознаватель привязывается к экземпляру UIView с помощью метода
addGestureRecognizer(_:). Для обработки жестов у представления должно быть свойствоisUserInteractionEnabled = true(по умолчаниюtrueдля интерактивных элементов, ноfalseдля UIImageView и UILabel). -
Target-Action паттерн: Инициализируется с целевым объектом (target) и методом-селектором (action), который будет вызван при распознавании жеста.
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) -
Состояния жеста (UIGestureRecognizer.State): В методе обработки можно анализировать состояние распознавателя, что особенно важно для непрерывных жестов (пан, пинч, вращение).
@objc func handlePan(_ gesture: UIPanGestureRecognizer) { let translation = gesture.translation(in: gesture.view?.superview) switch gesture.state { case .began: // Начало жеста case .changed: // Жест продолжается, обновляем позицию view gesture.view?.center.x += translation.x gesture.setTranslation(.zero, in: gesture.view?.superview) case .ended, .cancelled: // Жест завершен или отменен default: break } } -
Делегирование (UIGestureRecognizerDelegate): Протокол позволяет тонко настраивать поведение жестов. Ключевые методы:
* `gestureRecognizerShouldBegin(_:)` — разрешить или запретить начало распознавания.
* `gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)` — разрешить одновременное распознавание несколькими жестами (например, пинч и вращение). Возврат `true` позволяет одновременно масштабировать и вращать объект.
* `gestureRecognizer(_:shouldRequireFailureOf:)` и `gestureRecognizer(_:shouldBeRequiredToFailBy:)` — устанавливать приоритеты и зависимости между жестами.
Важные аспекты для разработчика
- Отмена и отказ: Система может отменить жест (например, при прерывании), или же распознаватель может перейти в состояние .failed, если движение не соответствует паттерну. Это важно для корректной обработки.
- Отношения между жестами: На одном UIView может быть несколько распознавателей. Поведение по умолчанию — один жест блокирует другие. Для одновременной работы или установки приоритета (например, двойной тап блокирует одинарный) используются методы делегата или настройки вроде
require(toFail:). - Наследование: Можно создавать собственные подклассы UIGestureRecognizer для распознавания нестандартных жестов, переопределяя методы обработки касаний (
touchesBegan,touchesMoved,touchesEnded,touchesCancelled) и корректно обновляяstate. - Взаимодействие с другими обработчиками: Жесты имеют более высокий приоритет, чем обычные обработчики касаний в UIResponder-цепочке. Но их можно интегрировать, используя ту же информацию об объектах UITouch.
Пример одновременного распознавания
class ViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var customView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotation(_:)))
// Назначаем делегата
pinchGesture.delegate = self
rotationGesture.delegate = self
customView.addGestureRecognizer(pinchGesture)
customView.addGestureRecognizer(rotationGesture)
}
// Разрешаем одновременное выполнение пинча и вращения
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return (gestureRecognizer is UIPinchGestureRecognizer && otherGestureRecognizer is UIRotationGestureRecognizer) ||
(gestureRecognizer is UIRotationGestureRecognizer && otherGestureRecognizer is UIPinchGestureRecognizer)
}
@objc func handlePinch(_ gesture: UIPinchGestureRecognizer) {
guard let view = gesture.view else { return }
view.transform = view.transform.scaledBy(x: gesture.scale, y: gesture.scale)
gesture.scale = 1.0 // Сброс масштаба
}
@objc func handleRotation(_ gesture: UIRotationGestureRecognizer) {
guard let view = gesture.view else { return }
view.transform = view.transform.rotated(by: gesture.rotation)
gesture.rotation = 0 // Сброс вращения
}
}
Итог: UIGestureRecognizer — это мощный и гибкий инструмент, который избавляет разработчика от необходимости вручную обрабатывать сложные последовательности касаний. Понимание его состояний, делегата и управления приоритетами жестов критически важно для создания отзывчивого, интуитивного и надежного пользовательского интерфейса в iOS-приложениях.