2011-01-09 25 views
8

Has estado buscando altas y bajas para esto:datos básicos: ejecución de interrupción NSFetchRequest

de materias básicas de datos, hay una manera de interrumpir/detener/cancelar y ejecutar NSFetchRequest?

Estoy implementando una búsqueda incremental en una aplicación para iPhone, y he intentado optimizarlo en todos los sentidos, pero no es suficiente (tengo 42,000 registros), así que tengo que ejecutarlo en una NSOperation. Cuando se escribe un nuevo carácter, necesito cancelar el fetchRequest anterior, pero [nsoperation cancel] no hace nada.

Otro enfoque podría ser mover el campo que estoy buscando en otro índice interrumpible, tal vez en la memoria, o tal vez una base de datos sqlite3 separada, que parece ser interrumpible con sqlite_interrupt.

Respuesta

2

Mi solución fue permitir que las operaciones de consulta sigan ejecutándose, pero para verificar si se habían cancelado antes de enviar el evento para actualizar la UI.

Esto no es perfecto porque todavía puede tener una gran cantidad de operaciones de consulta en ejecución, cuyos resultados nunca se utilizarán, pero todavía es bastante más rápido.

2

Respuesta corta - no, no directamente, lo siento.

Respuesta larga - Sí, pero hay que hacer un poco o trabajar para hacerlo

Usted tendrá que ejecutar en un subproceso de fondo (que suena como que ya está haciendo a través de NSOperation)

En su búsqueda, establezca el límite para obtener 20 resultados a la vez y ejecútelo en un bucle. Cada vez que pasa el ciclo, agregue los resultados que obtiene a una matriz. Cada vez que la búsqueda obtiene cada conjunto de resultados, verifique si desea cancelar la solicitud.

+2

Esto último no funciona porque para una consulta ordenada, toma casi el mismo tiempo para obtener los primeros 20 como la primera n. – mclin

1

En realidad tuve el mismo problema que usted. Para resolverlo uso un método performSelector:afterDelay:

Es un poco complicado, pero cuando el usuario escribe rápidamente 3 letras rápidamente, no quiero enviar 3 solicitudes, pero solo una cuando el usuario terminó de escribir. Configuré un pequeño retraso de 0.5 o más.

Utilizando este código:

[NSObject cancelPreviousPerformRequestsWithTarget:self]; 
[self performSelector:@selector(fetchSearch:) withObject:searchQuery afterDelay:0.5]; 

Si el usuario escribe rápido, que cancelará las solicitudes anteriores y enviar sólo el último.

14

La respuesta directa a su pregunta es no. Su mejor opción, con su diseño actual, es hacerlas en una operación, pero luego tiene la barrera de hilos de la que preocuparse y la velocidad. Tenga en cuenta que si sus operaciones no se están ejecutando en el hilo principal, entonces necesita un NSManagedObjectContext por separado para la operación o se encontrará con problemas de enhebrado.

Mejor pregunta: ¿Por qué estás haciendo una nueva búsqueda para cada personaje?

Si ya tiene los resultados de búsqueda de una búsqueda anterior y el usuario no eliminó un carácter, solo tome los resultados existentes y ejecute su predicado contra el NSArray. Eso refinará aún más la búsqueda en lugar de ir al disco cada vez. Como está en la memoria, será extremadamente rápido.

considerar las siguientes opciones en la aplicación de un campo de búsqueda:

  • Hit sólo el disco en el primer carácter
  • Hit el disco sólo si un carácter es eliminado del cuadro de búsqueda
  • contemplar la precarga del objectID y la propiedad de búsqueda para evitar golpes de disco.

Dependiendo de lo que está buscando (y hay maneras de renormalizar el almacén de datos básicos para mejorar la búsqueda) se puede precargar un poco en la memoria. Incluso con 42K registros si las propiedades de búsqueda son lo suficientemente pequeñas, puede cargarlas todas en la memoria.

Lo más probable es que tenga que probar ese caso de uso de todos modos si el usuario comienza presionando "A".

¿Qué parte de NSFetchRequest es lenta? ¿Toca la base de datos SQLite o carga los datos en la memoria? En función de su respuesta, puede mejorar el rendimiento de búsqueda directamente.

+0

¡Brillante, gracias! – JOM

+0

También debería "pulsar el disco" si se insertó algún carácter en el texto de búsqueda. Por ejemplo, un usuario puede escribir "fooar" y luego corregirlo insertando el carácter que falta y luego la siguiente búsqueda sería "foobar". – Sean

Cuestiones relacionadas