NSPredicate de dados principais “deleted == NO” não funciona como esperado

Eu estou usando o contexto UIManagedDocument com pai filho.

No meu contexto infantil, faço o seguinte

Código 1

NSSet *results = [self.event.memberships filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { return ([[evaluatedObject deleted] boolValue] == NO); }]]; 

O código acima retorna os resultados esperados (somente os membros não excluídos do evento).

Código 2

Mas esse código não. Ele busca todos os registros.

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"deleted == NO"]; NSSet *results = [self.event.memberships filteredSetUsingPredicate:predicate]; 

Parece confuso. Ambos devem retornar os mesmos resultados, mas predicateWithBlock retorna resultados corretos onde, como predicateWithFormat retorna todos os registros.

Quais são os prós e contras de usar predicateWithBlock vez de predicateWithFormat ?

O problema é que você definiu um atributo deleted para sua entidade. Isso entra em conflito com o método isDeleted de NSManagedObject , portanto, você deve renomear esse atributo.

O “experimento” a seguir mostra que coisas estranhas acontecem se você chamar seu atributo “deleted” ( c é um object gerenciado com um atributo personalizado deleted ):

 // Set custom "deleted" property to YES: c.deleted = @YES; // Use the property, as your Code 1 NSLog(@"%@", [c deleted]); // Output: 1 // Use Key-Value Coding, as your Code 2 NSLog(@"%@", [c valueForKey:@"deleted"]); // Output: 0 // Now really delete the object and try again: [context deleteObject:c]; NSLog(@"%@", [c valueForKey:@"deleted"]); // Output: 1 

Seu “Código 1” refere-se à propriedade, portanto, retorna o resultado esperado. “Código 2” usa Codificação de valor-chave e [c valueForKey:@"deleted"] retorna YES se o object tiver sido realmente excluído do contexto!

Então, renomear esse atributo deve resolver seu problema. Infelizmente, o compilador não emite avisos se um nome de atributo entrar em conflito com um método interno.

Use o espaço reservado de formatação para replace o valor bool:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"deleted", @(NO)];

Seu uso do caminho da chave provavelmente é ok, mas o lado direito provavelmente não se parece com “NÃO” para o analisador.