2012-06-26 25 views
8

Esto es bastante divertido. En mi aplicación, creo miles de entradas en la base de datos (en otro hilo, estoy usando MagicalRecord). Todo parece funcionar bien (desde un punto de vista de fondo/primer plano/contexto).NSPredicate no ejecutado

Cuando, en el hilo principal, trato de recuperar los datos "acaba de insertar", descubrí el siguiente comportamiento:

- (NSArray *) familiesInCompany:(Company *) company { 
    NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"company == %@", company]; 
    NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"company.name == %@", company.name]; 

    NSArray *first = [Family MR_findAllSortedBy:@"name" ascending:YES withPredicate:predicate1]; 
    NSArray *second = [Family MR_findAllSortedBy:@"name" ascending:YES withPredicate:predicate2]; 
    NSArray *third = [Family MR_findByAttribute:@"company" withValue:company andOrderBy:@"name" ascending:YES]; 

    return second; 
} 

Ahora lo que consigo es:

  • primera: es una matriz vacía
  • segundos: contiene todos los Family objetos, como se esperaba
  • tercera: es una matriz vacía.

Por la depuración de la instrucción SQL consigo el siguiente:

La "primera" declaración:

CoreData: anotación: tiempo total de ejecución tomará: 0.0000s de 0 filas.

La "segunda" declaración ":

CoreData: SQL: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZCOMPANY DE ZFAMILY t0 t1 JOIN ZCOMPANY EN T0. ZCOMPANY = t1.Z_PK DONDE t1.ZNAME = ORDER BY t0.ZNAME

CoreData:? anotación: conexión de SQL buscar a tiempo: 0.0005s

CoreData: anotación: tiempo total de ejecución ir a buscar: 0.0007s de 2 filas.

El "tercer" declaración:

CoreData: anotación: ir a buscar total de tiempo de ejecución: 0.0000s de 0 filas.

Lo gracioso es que cierro la aplicación (me refiero a realmente termino manualmente) y y abro de nuevo, todos los tres estados "ir a buscar" funcionan.

¿Por qué la primera y la tercera instrucción de búsqueda parecen no ejecutarse nunca? ¿Cómo profundizar en el problema?

+0

Teniendo esencialmente el mismo problema, creo, con una implementación de NSFetchedResultsController. Los registros creados recientemente no se muestran en el resultado de búsqueda, sino que se escriben en el almacén persistente cuando lo compruebo directamente: el recuento correcto incluso aparece en la relación NSSet, pero el NSPredicate no los ve. Extraño. Uso de MagicalRecord 2: utilicé una versión 1.x para un proyecto anterior y no tuve problemas, así que simplemente puedo cambiar el curso y usar una versión anterior. –

+0

Pregunta ingenua (y algo fuera de tema): ¿cómo estás registrando las sentencias sql? Tengo mucha curiosidad sobre cómo hacer eso en mi aplicación para comprender mejor los predicados –

+1

@FelipeSabino ver http://stackoverflow.com/questions/6428630/xcode4-and-core-data-how-to-enable-sql-debugging y http://d.pr/i/Lszs –

Respuesta

8

Tuve este mismo problema, esto es lo que descubrí y cómo lo resolví.

Magical Record tiene una raíz NSManagedObjectContext como elemento principal del valor predeterminado NSManagedObjectContext. Cuando creo un NSFetchedResultsController en el contexto predeterminado, todo parece funcionar bien, igual que usted.

El problema es que todos los nuevos NSManagedObject 's vuelven con sus todavía-temporales ObjectID' s. Entonces, en mi caso, estaba usando un NSPredicate para determinar el alcance de una consulta en una tabla asociada.No llamé simplemente al método de asociación porque no quería cargar todo en la memoria y quería NSFetchedResultsController para manejar los cambios, para mí.

Con la ObjectID temporal, la consulta no encuentra ningún resultado y eso es exactamente lo que muestra.

Aparentemente, el contexto secundario (predeterminado) no obtiene el beneficio de la transformación a ID no temporales, aunque se haya conservado en el almacén de respaldo.

Incluso peor maldad sucedió cuando traté de forzar el problema con obtainPermanentIDsForObjects:error:. Core Data se quejó de que no podría satisfacer un error para mi instancia. No importa, no hay manera de que fuera realmente una falla. Simplemente refrescar el objeto tampoco tuvo efecto. Sospecho que este es un error de Core Data que casi nadie hace cosquillas porque solo usan los métodos de asociación para obtener un NSSet.

Mi solución fue utilizar el contexto principal para el NSFetchedResultsController, al igual que en esta pregunta, Magical Record, saving, and NSFetchedResultsController.

Ya estaba envolviendo el valor predeterminado en un nuevo contexto secundario al editar y, por lo tanto, copiando las instancias en ese contexto de edición con createInContext, así que no tuve que hacer ningún trabajo adicional más allá de simplemente agregar .parentContext al argumento.

Dicho sea de paso, esto solo ocurrió en nuevas instancias de la fuente de la asociación. Una vez que una instancia estaba allí desde el inicio, tenía un ObjectID no temporal y nunca tuvo el problema.

+0

Lo siento, creo que me perdí algo. ¿Su consejo es crear los "recursos" usando el "currentContext.parentContext"? –

+0

No del todo, eso es lo que paso al método Mágico registro fetch *. La creación (y modificación) de objetos tiene lugar en un contexto secundario con MR_defaultContext con su padre. – Otto

+0

Código de ejemplo, [Modelo fetchAllSortedBy: @ "qqq" ascendente: NO conPredicado: grupo de predicadosPor: @ "qqq" delegado: self enContexto: self.managedObjectContext.parentContext]; En este caso, self.managedObjectContext es lo mismo que MR_defaultContext. – Otto

Cuestiones relacionadas