que - ¿Debería el gesto de Superview cancelar el gesto de la subvista en iOS 7?
como desactivar el boton home del iphone (1)
Después de buscar mucho, encontré una discusión en los tableros de mensajes de Apple con otros usuarios que tienen este problema: Problemas con UITapGestureRecognizer (se requiere una cuenta de desarrollador). Seguí adelante y envié un informe de error: 15331126 (¿alguien sabe ya cómo vincular los informes de fallas?) . Mientras tanto, implementé esta solución. Hasta ahora parece estar funcionando, pero dado que el error es tan raro, es posible que simplemente no lo haya activado aún. Lo estoy lanzando a mis usuarios beta y si no recibo quejas de ellos (que se han estado quejando) supongo que esto soluciona el problema.
ACTUALIZACIÓN: esta solución ha solucionado el problema. Después de semanas de uso por docenas de usuarios, no he tenido un solo problema con los gestos.
La mayoría de mis gestos son personalizados. Los alteré para que fueran delegados de ellos mismos e implementados:
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if (gestureRecognizer == self){
if ([otherGestureRecognizer isMemberOfClass:self.class]){
if ([self isGestureRecognizerInSuperviewHierarchy:otherGestureRecognizer]){
return YES;
} else if ([self isGestureRecognizerInSiblings:otherGestureRecognizer]){
return YES;
}
}
}
return NO;
}
Tenga en cuenta que mis gestureRecognizers personalizados implementan el protocolo UIGestureRecognizerDelegate ahora (públicamente, por las razones que verá a continuación). También agregué un par de categorías a UIGestureRecognizer (usado en el código anterior):
- (BOOL) isGestureRecognizerInSiblings:(UIGestureRecognizer *)recognizer{
UIView *superview = self.view.superview;
NSUInteger index = [superview.subviews indexOfObject:self.view];
if (index != NSNotFound){
for (int i = 0; i < index; i++){
UIView *sibling = superview.subviews[i];
for (UIGestureRecognizer *viewRecognizer in sibling.gestureRecognizers){
if (recognizer == viewRecognizer){
return YES;
}
}
}
}
return NO;
}
- (BOOL) isGestureRecognizerInSuperviewHierarchy:(UIGestureRecognizer *)recognizer{
if (!recognizer) return NO;
if (!self.view) return NO;
//Check siblings
UIView *superview = self.view;
while (YES) {
superview = superview.superview;
if (!superview) return NO;
for (UIGestureRecognizer *viewRecognizer in superview.gestureRecognizers){
if (recognizer == viewRecognizer){
return YES;
}
}
}
}
No estoy del todo seguro de que deba verificar si tengo hermanos, ya que solo he visto que el problema ocurre con gestos de supervisión. Sin embargo, no quería tomar esa oportunidad. Tenga en cuenta que solo verifico si hay hermanos "debajo" de la actual ya que no quiero cancelar los gestos de vista "arriba" de la vista actual.
Tuve que agregar implementaciones para aquellas clases que se configuraron como delegados de los reconocedores personalizados, pero prácticamente devuelven la llamada al gestureRecognizer:
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if ([gestureRecognizer respondsToSelector:@selector(gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:)]){
return [(id <UIGestureRecognizerDelegate>)gestureRecognizer gestureRecognizer:gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:otherGestureRecognizer];
}
return NO;
}
Espero que esto ayude a cualquier otra persona que tenga el problema.
Desde hace varios años opero bajo la suposición de que si una supervista y su subvista tienen reconocedores de gestos, la subvista recibiría primero los toques y cancelaría el gesto de la supervista. Hasta el iOS 7, esta suposición nunca me falló, permitiéndome agregar gestos a las subvistas con la confianza de que los gestos de la supervista no interferirían. Pero en iOS 7, la supervista recibirá aleatoriamente los toques primero y cancelará los gestos de la subvista. Esto ocurre de forma algo rara, lo que dificulta el problema.
Primero experimenté este problema como botones que no se podían UITapGestureRecognizer
con UITapGestureRecognizer
... de nuevo, muy raramente. Usualmente los botones funcionarían hasta que no lo hicieran. Te hizo cuestionar tu cordura. Así que TapGestureRecognizer
mi propio TapGestureRecognizer
y descubrí que los grifos de superview estaban cancelando los grifos de su subvista ocasionalmente. Nunca lo he hecho en ninguna versión anterior de iOS, pero me pregunto si este comportamiento simplemente nunca se prometió.
Pensé que el gesto de la subvista se suponía que cancelara el gesto de la supervista (a menos que un delegado especifique lo contrario). ¿Esto está mal o es esto un error?
Tenga en cuenta: no estoy preguntando cómo manejar la situación. Pregunto si alguien sabe si mi suposición es incorrecta. Ya estoy reorganizando vistas, agregando / eliminando gestos dinámicamente y creando implementaciones bastante complejas de gestureRecognizer:shouldReceiveTouch:
para remediar la situación. No es divertido, pero puedo evitar el problema.