sensibilidad plus pantalla calibrar assistive ajustar ios pointers reference multi-touch touchesbegan

ios - plus - ¿Cómo rastrear los toques de forma consistente entre los toques de Began: y toques?



sensibilidad pantalla iphone 6 plus (3)

En algún mantenimiento de un código multitáctil de "dibujo en pantalla", encontré un error relativo a cómo las referencias a las instancias de toques deben establecerse entre toques. Comienzo: conEvento :, toquesMovimiento: conEvento: y toquesEntrada: conEvento :.

El código usa una instancia de NSDictionary para almacenar referencias de toques en touchesBegan: withEvent :, de la siguiente manera:

for (UITouch *touch in touches]) { NSValue *touchValue = [NSValue valueWithPointer:touch]; NSString *key = [NSString stringWithFormat:@"%@", touchValue]; [myTouches setValue:squiggle forKey:key]; }

Y los recupera en toquesEnded: withEvent: de esta manera:

for (UITouch *touch in touches) { NSValue *touchValue = [NSValue valueWithPointer:touch]; NSString *key = [NSString stringWithFormat:@"%@", touchValue]; NSObject *valueFromDictionary = [myTouches valueForKey:key]; [myTouches removeObjectForKey:key]; }

En este último bit de código, valueFromDictionary pasa a ser ocasionalmente nulo, ya que la clave no es conocida por el diccionario. De vez en cuando, me refiero a aproximadamente el 1% del tiempo.

Ahora que el contexto está establecido, mis preguntas son:

  1. ¿Alguna idea de por qué este código tiene errores? No estoy seguro de por qué no funciona, especialmente debido a la baja frecuencia de errores

  2. Algunos documentos de Apple afirman que es una buena idea usar direcciones de los objetos UITouch como claves : pero significa usar objetos NSValue * en lugar de objetos NSString * ( y en consecuencia usar CFDictionaryRef en lugar de NSDictionary debido a que UITouch no implementa la copia protocolo). ¿Por qué almacenar una representación en NSString de la dirección en lugar de la NSValue en sí misma no puede ser una solución fácil para poder usar NSDictionary? Actualización: Apple ha actualizado la página y eliminado el ejemplo de almacenamiento de un UITouch a través de un NSString y solo menciona la solución CFDictionaryRef que no requiere nada.

Me temo que estoy lejos de las cosas de C e indicadores y necesito ayuda para entender la razón por la cual hay un error en este código.


Cuando utiliza stringWithFormat para convertir la instancia de NSValue en una cadena, creo que básicamente está llamando [descripción de touchValue], lo que no estoy seguro garantiza un resultado consistente. Por ejemplo, ¿qué ocurre si la descripción incluye un puntero a la instancia de NSValue, como lo hacen muchos objetos? En ese caso, dos instancias de NSValue diferentes que almacenen el mismo puntero producirán claves de cadena diferentes.

Me interesaría ver qué sucede cuando ejecutas el siguiente código:

for (UITouch *touch in touches) { NSValue *touchValue = [NSValue valueWithPointer:touch]; NSString *key = [NSString stringWithFormat:@"%@", touchValue]; NSObject *valueFromDictionary = [myTouches valueForKey:key]; if (valueFromDictionary == nil) { NSLog(@"%@", [myTouches allKeys]); NSLog(@"%@", key); } [myTouches removeObjectForKey:key]; }

Esto nos diría exactamente qué está cambiando con respecto a la clave. Pero si prefieres solo solucionar el problema que tienes, apuesto a que funcionaría si usaras el objeto NSValue como clave directamente, ya que cumple con el protocolo NSCopying. Básicamente, el puntero (UITouch *) es solo un número que identifica de forma única dónde se almacena la instancia de UITouch en la memoria. NSValue encapsula este número de la misma manera que lo haría NSNumber, por lo que podría pensarlo como una clave numérica en la matriz. Siempre que el toque continúe ocupando la misma ubicación en la memoria (como Apple sugiere), debería funcionar perfectamente como una clave, y su código sería más simple:

(touchesBegan: withEvent :)

for (UITouch *touch in touches]) { NSValue *key = [NSValue valueWithPointer:touch]; [myTouches setValue:squiggle forKey:key]; }

(toquesEnded: withEvent :)

for (UITouch *touch in touches) { NSValue *key = [NSValue valueWithPointer:touch]; NSObject *valueFromDictionary = [myTouches valueForKey:key]; [myTouches removeObjectForKey:key]; }

Realmente no hay ninguna razón para limitarse a las claves de cadena, a menos que necesite usar codificación de clave-valor o serializar el diccionario a una lista de propiedades.


No usar

NSString *key = [NSString stringWithFormat:@"%@", touchValue];

para la llave. La mejor forma sería establecer el valor del puntero táctil como una clave

id key = touch;

o si prefiere cadenas, use este caso:

NSString *key = [NSString stringWithFormat:@"%x", touch]; // %x prints hex value of touch


Puede usar el hash de la propiedad UITouch tanto para ObjC como para Swift. Es lo mismo con el mismo toque en varios eventos (Arriba, Abajo, Mover, etc.). Es un Int pero puedes convertirlo a String