usa iphone

iphone - usa - ¿Cuál es el truco para pasar un evento al siguiente respondedor en la cadena de respondedores?



iphone xr (8)

De acuerdo con una pregunta similar , su método debería funcionar.

Esto me lleva a pensar que el siguienteResponder de tu vista no es realmente el ViewController , como sospechas.

Me gustaría agregar un NSLog rápido en su código de reenvío para verificar lo que realmente apunta su siguienteResponder:

if (numTaps < 2) { NSLog(@"nextResponder = %@", self.nextResponder); [self.nextResponder touchesBegan:touches withEvent:event]; }

También puede cambiar sus otros mensajes de NSLog para que generen información de tipo y dirección:

NSLog(@"touched %@", self);

touched <UIView 0x12345678>

Esto debería ayudarle a comenzar a diagnosticar el problema.

Apple es muy divertido. Quiero decir, dicen que esto funciona:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* touch = [touches anyObject]; NSUInteger numTaps = [touch tapCount]; if (numTaps < 2) { [self.nextResponder touchesBegan:touches withEvent:event]; } else { [self handleDoubleTap:touch]; } }

Tengo un controlador de vista. Como usted sabe, los controladores de vista heredan de UIResponder. Ese controlador de vista crea un objeto MyView que hereda de UIView y lo agrega como una subvista a su propia vista.

Entonces tenemos:

Ver Controlador> tiene una Vista (automáticamente)> tiene una MyView (que es una UIView).

Ahora, dentro de MyView, puse ese código como arriba con un NSLog que imprime "toque MyView". Pero reenvío el evento al siguiente respondedor, al igual que arriba. Y dentro del ViewController tengo otro método touchesBegan que simplemente imprime un NSLog a la "control de vista tocado".

Ahora adivina qué: cuando toco el MyView, se imprime "toque MyView". Cuando toco fuera de MyView, que es la vista del VC, obtengo un "controlador de vista tocado". Así que ambos trabajan! Pero lo que no funciona es reenviar el evento. Porque ahora, en realidad, el siguiente respondedor debería ser el controlador de vista, ya que no hay nada más entre ellos. Pero el método de manejo de eventos del VC nunca se llama cuando lo reenvío.

PS

Ideas?

Averiguar cosas raras El siguiente respondedor de MyView es la vista del controlador de vista. Eso tiene sentido, porque MyView es una subvista de eso. Pero no modifiqué este UIView desde el controlador de vista. No es nada personalizado. Y no implementa ningún manejo de eventos táctiles. ¿No debería pasar el mensaje al controlador de vista? ¿Cómo podría dejarlo pasar? Si elimino el código de manejo de eventos en MyView, entonces el evento llega muy bien en el controlador de vista.


Hoy he encontrado un mejor método para solucionar esto o la pregunta como esta.

En su UITableViewCell, puede agregar un delegado para escuchar el evento táctil, como esto:

@protocol imageViewTouchDelegate -(void)selectedFacialView:(NSInteger)row item:(NSInteger)rowIndex; @end @property(nonatomic,assign)id<imageViewTouchDelegate>delegate;

Luego en el UITableViewController: puedes hacer esto así:

@interface pressionTable : UITableViewController<facialViewDelegate>

y en el archivo .m puede implementar esta interfaz de delegado, como:

-(void)selectedFacialView:(NSInteger)row item:(NSInteger)rowIndex{ //TO DO WHAT YOU WANT}

NOTA: cuando inicia la celda, debe establecer el delegado; de lo contrario, el delegado no es válido, puede hacerlo de la siguiente manera.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; pressionCell *cell = (pressionCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[pressionCell alloc]initWithFrame:CGRectMake(0, 0, 240, 40)]; } cell.delegate = self;

}

PD: Sé que este DOC es antiguo, pero sigo agregando mi método para solucionar la pregunta, de modo que cuando las personas se encuentren con el mismo problema, obtendrán ayuda con mi respuesta.


Para hacer referencia a un controlador de vista, necesita usar

[[self nextResponder] nextResponder]

porque [self nextResponder] significa la vista de un controlador de vista, y [[self nextResponder] nextResponder] significa el controlador de la vista en sí, ahora puede obtener el evento táctil


Sé que esta publicación es antigua pero pensé en compartir porque tuve una experiencia similar. Lo arreglé configurando userInteractionEnabled en NO para la vista del controlador de vista que se creó automáticamente.


Sí, debería funcionar al 100% en caso común. Acabo de probar con el proyecto de prueba y todo parece estar bien.

He creado una aplicación basada en la vista. Usando Interface Builder, coloque el nuevo UIView en la vista actual. Luego cree un nuevo archivo con la subclase de UIView y seleccione la clase recién creada para mi nueva vista. (Interface Builder-> Identidad de clase-> Clase-> MyViewClass)

Agregue funciones de controlador de toques para MyViewClass y UIViewController.

// MyViewClass

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"myview touches"); [self.nextResponder touchesBegan:touches withEvent:event]; }

// ViewController

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"controller touches"); }

Veo ambos NSLogs cuando presiono MyViewClass. ¿Usó Interface Builder y el archivo XIB cuando cargó su ViewController o configuró la vista programáticamente con la función loadView?


Si nos fijamos en la documentación de UIResponder la descripción dice que por defecto:

UIView implementa este método devolviendo el objeto UIViewController que lo administra (si tiene uno) o su supervisión (si no lo tiene);

Si su vista no está devolviendo el controlador de vista, debe devolver su supervisión de supervisión (entonces, como se dio cuenta).

UIApplication en realidad tiene un método que se supone que maneja este caso de uso exactamente:

- (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event

Ya que no tiene una referencia al objetivo, puede avanzar en la cadena de respondedores estableciendo el valor objetivo como nil ya que de acuerdo con la documentación:

Si el objetivo es nulo, la aplicación envía el mensaje al primer respondedor, desde donde progresa en la cadena de respondedores hasta que se maneja.

Por supuesto, puede obtener acceso a la UIApplication con su método de clase [UIApplication sharedApplication]

Más información aquí: UIApplication documents

Esto es adicional, pero si es absolutamente necesario acceder al controlador de vista para hacer algo un poco más complejo, puede avanzar manualmente en la cadena de respondedores hasta que llegue al controlador de vista llamando al método nextResponder hasta que devuelva un controlador de vista. Por ejemplo:

UIResponder *responder = self; while ([responder isKindOfClass:[UIView class]]) responder = [responder nextResponder];

entonces puedes simplemente convertirlo en tu controlador de vista y continuar haciendo lo que quieras hacer con él:

UIViewController *parentVC = (UIViewController *)responder


Tenía problemas con esto, ya que mi vista personalizada era más profunda en la jerarquía de vistas. En cambio, subí la cadena de respuesta hasta que encuentra un UIViewController ;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // Pass to top of chain UIResponder *responder = self; while (responder.nextResponder != nil){ responder = responder.nextResponder; if ([responder isKindOfClass:[UIViewController class]]) { // Got ViewController break; } } [responder touchesBegan:touches withEvent:event]; }


utilizar esta

[super.nextResponder touchesBegan:touches withEvent:event];

antes de esta linea en tu codigo

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

significa

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* touch = [touches anyObject]; NSUInteger numTaps = [touch tapCount]; if (numTaps < 2) { [super.nextResponder touchesBegan:touches withEvent:event]; [self.nextResponder touchesBegan:touches withEvent:event]; } else { [self handleDoubleTap:touch]; } }

** Versión Swift 4 **

func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) { let touch = touches?.first as? UITouch let numTaps: Int? = touch?.tapCount if (numTaps ?? 0) < 2 { if let aTouches = touches as? Set<UITouch> { super.next?.touchesBegan(aTouches, with: event) next?.touchesBegan(aTouches, with: event) } } else { handleDoubleTap(touch) } }