Ответ
Нет. Установка isUserInteractionEnabled = false для родительской UIView полностью отключает обработку всех событий касания (UITouch) для всей её иерархии subviews. Это свойство имеет каскадный эффект.
Пример, демонстрирующий проблему:
let containerView = UIView()
containerView.isUserInteractionEnabled = false // Отключает взаимодействие для всех subviews
let button = UIButton(type: .system)
button.setTitle("Tap Me", for: .normal)
button.addTarget(self, action: #selector(handleTap), for: .touchUpInside)
containerView.addSubview(button)
// Касание по кнопке НИКОГДА не вызовет `handleTap`.
Обходные пути:
- Включить взаимодействие у родителя (
isUserInteractionEnabled = true). - Переопределить
hitTest(_:with:)у родительской вью, чтобы точечно передавать события определённым subviews. - Использовать
UIGestureRecognizerна subview (но он также не сработает, если родитель отключён).
Основное правило: если родитель не взаимодействует, то и его дети — тоже.
Ответ 18+ 🔞
А, ну это классика, блядь! Ситуация, от которой у любого iOS-разработчика волосы дыбом встают, а потом начинают выпадать клочьями, ёпта.
Смотри, представь себе такую картину. Есть у тебя контейнер, UIView, здоровенный такой, как шкаф. И ты ему командуешь: «Шкаф, стой, блядь, смирно! Не реагируй ни на какие пиздюли!» — isUserInteractionEnabled = false. И ты думаешь, ну всё, порядок, я главный.
А потом ты в этот шкаф, в эту нереагирующую хуйню, засовываешь кнопку, красивую такую, с надписью «Нажми меня, сука!». И наивно полагаешь, что раз кнопка-то вроде как живая, то и нажмётся. Ан хуй там плавал!
let containerView = UIView()
containerView.isUserInteractionEnabled = false // Всё, пиздец. Шкафу приказано не дышать.
let button = UIButton(type: .system)
button.setTitle("Жми сюда, долбаёб!", for: .normal)
button.addTarget(self, action: #selector(handleTap), for: .touchUpInside)
containerView.addSubview(button)
// Тыкаешь в кнопку до посинения, а `handleTap` молчит, как Герасим из рассказа Тургенева. Просто «Му-му», блядь, и всё.
Вот в чём, сука, магия, а точнее, ёбаный трюк системы: свойство isUserInteractionEnabled — оно каскадное, как водопад, блядь! Если у родителя стоит false, то все его дети, внуки и правнуки в иерархии вьюх становятся такими же бесполезными, как мои обещания начать бегать по утрам. Система просто не будет даже пытаться искать, куда тыкнули, внутри этой мёртвой зоны. События касания туда не доходят, их там, блядь, не существует!
Так как же выкрутиться, если очень надо? Варианты есть, но они, как обычно, с подвохом, ебать мои старые костыли.
-
Самый очевидный, но не всегда возможный. Разблокировать шкаф! Поставить родителю
isUserInteractionEnabled = true. Но иногда это нельзя, потому что тогда и сам шкаф начнёт ловить тапы, а это не входит в твои, блядь, коварные планы. -
Хакерский метод, для извращенцев. Переопределить у родительской вью метод
hitTest(_:with:). Это типа как поставить у шкафа умного охранника, который будет смотреть: «Ага, тычут не в меня, а в мою кнопку-внучку. Ладно, проходи, событие, передаю тебя дальше». Но это уже надо код писать, мозги напрягать, а не просто флажок переключить. -
Наивный и обречённый. Повесить
UIGestureRecognizerпрямо на сабвью (на ту же кнопку). И думать: «Ну я же ж на саму кнопку вешаю, при чём тут родитель?». А при том, блядь, что жест тоже будет молчать, как партизан на допросе. Потому что события до него просто не дойдут, их отец-шкаф на входе отфильтровал!
Так что запомни раз и навсегда, как «Отче наш»: если родитель — интерактивный овощ (false), то и все его дети — такие же интерактивные овощи. Система так устроена, и спорить с ней — это как сраться с лужей: обосрёшься только сам.