¿Cómo ignorar los events táctiles y pasarlos a los objects UIControl de otra subvista?

Tengo un UIViewController personalizado cuya UIView toma una esquina de la pantalla, pero la mayor parte es transparente, excepto las partes que tienen algunos botones y otras cosas. Debido al layout de los objects en esa vista, el marco de la vista puede cubrir algunos botones debajo. Quiero poder ignorar cualquier toque en esa vista si no tocan algo importante en él, pero parece que solo puedo pasar a través de events táctiles reales (toquesEnded / nextResponder stuff). Si tengo un button UIB o algo así que no use touchesEnded, ¿cómo paso el evento táctil a eso?

No puedo simplemente averiguar manualmente el selector de botones para llamar, ya que este ViewController personalizado se puede usar en muchas vistas diferentes. Básicamente necesito una forma de llamar a esto:

[self.nextResponder touchesEnded:touches withEvent:event];

en types UIControl también.

Probablemente la mejor manera de hacerlo es anular hitTest:withEvent: en la vista que desea ignorar toques. Dependiendo de la complejidad de la jerarquía de su vista, hay algunas forms sencillas de hacerlo.

Si tiene una reference a la vista debajo de la vista para ignorar:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; // If the hitView is THIS view, return the view that you want to receive the touch instead: if (hitView == self) { return otherView; } // Else return the hitView (as it could be one of this view's buttons): return hitView; } 

Si no tiene una reference a la vista:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; // If the hitView is THIS view, return nil and allow hitTest:withEvent: to // continue traversing the hierarchy to find the underlying view. if (hitView == self) { return nil; } // Else return the hitView (as it could be one of this view's buttons): return hitView; } 

Recomendaría el primer enfoque como el más robusto (si es posible get una reference a la vista subyacente).

No he encontrado una buena forma de pasar events UITouch entre objects. Lo que generalmente funciona mejor es implementar hitTest y devolver nil si el punto no está en la vista que desea manejar:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

Respuesta rápida:

Puede crear una subclass UIView, IgnoreTouchView. En un guión gráfico, configúrelo en la (s) vista (s) de VC (s) con las que desea pasar toca:

 class IgnoreTouchView : UIView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let hitView = super.hitTest(point, with: event) if hitView == self { return nil } return hitView } } 

¡Tenga en count que debe establecer UserInteractionEnabled en true, para la UIView en cuestión!

Esta es una pregunta antigua y aparece en la parte superior de las búsquedas. Por lo tanto, pensé que publicaría otra posible solución que podría funcionar mejor para su situación. En mi caso, quería arrastrar una label encima de otra label y quería get la label a continuación en el hitTest. Lo más sencillo es configurar userInteractionEnabled en NO o false , luego hacer su userInteractionEnabled de userInteractionEnabled y luego volver a configurarlo si necesita moverlo nuevamente. Aquí hay una muestra de código en Swift:

 override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { let touch = touches.first let location = touch?.locationInView(self.view) self.label1.userInteractionEnabled = false let view = self.view.hitTest(location!, withEvent: nil) as? UILabel print(view?.text) self.label1.userInteractionEnabled = true } 

Mi problema fue similar: tenía un UIControl con respondedores táctiles complejos, pero actuaba divertido cuando estaba embedded en una vista de desplazamiento …

Esto evita el desplazamiento de los padres (o puede modificarse para evitar otras interacciones) cuando la vista secundaria tiene un gesto táctil activo.

Mi solución:

Cree un protocolo de delegado para didBeginInteraction y didEndInteraction en sub vista.

Llame a delegate.didBeginInteraction desde touchesBegan

Llame a delegate.didEndInteraction desde touchesEnded y toca Canceled

En el controller principal, implementar el protocolo didBegin y didEnd, establecer delegado

Luego, configure scrollView.scrollEnabled = NO en didBegin, scrollEnabled = YES en didEnd.

Espero que esto ayude a alguien con un caso de uso ligeramente diferente a la pregunta planteada.