2011-10-08 11 views
5

Sto cercando di ottenere un risultato distinto da NSPredicate.NSFetchRequest con proprietà distinte

Il mio codice:

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Members" inManagedObjectContext:context]; 
    request.entity = entity; 
    request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"city" 
                        ascending:YES 
                         selector:@selector(caseInsensitiveCompare:)]]; 

    request.predicate = [NSPredicate predicateWithFormat:@"memberDeleted == %@", [NSNumber numberWithBool:NO]]; 

    NSDictionary *properties = [entity propertiesByName]; 
    request.propertiesToFetch = [NSArray arrayWithObject:[properties objectForKey:@"city"]]; 
    request.returnsDistinctResults = YES; 

    request.fetchBatchSize = 20; 

    NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request 
                      managedObjectContext:context 
                      sectionNameKeyPath:nil 
                        cacheName:@"CityCache"]; 
    [request release]; 

    self.fetchedResultsController = frc; 
    [frc release]; 

Il problema è che il risultato ritorna molte volte la stessa città. Questa Entità ha molti Membri e ogni Membro ha una "città" di proprietà.

Cosa sto sbagliando?

Grazie,

RL

risposta

7

Assicurarsi di impostare il resultType del NSFetchRequest-NSDictionaryResultType. L'impostazione predefinita è di restituire gli oggetti effettivi e pertanto ignorerà propertiesToFetch.

+0

Probabilmente dovrei aggiungere che 'NSFetchedResultsController' non è generalmente un fan del' NSDictionaryResultType'. Potresti incontrare altri problemi e abbandonare il 'NSFetchedResultsController'. – Alex

+0

La domanda è che non voglio che il risultato sia e NSDictionary. In caso contrario, dovrò cambiare parte del mio codice. È fattibile in altro modo? –

+0

Quale oggetto ti aspetti che ritorni, quindi? I dati principali possono restituire solo oggetti effettivamente presenti nel grafico dell'oggetto. – Alex

6

Con l'aiuto di @alex, ecco il codice finale, senza FRC:

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Members" inManagedObjectContext:self.managedObjectContext]; 
request.entity = entity; 
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"city" 
                       ascending:YES 
                        selector:@selector(caseInsensitiveCompare:)]]; 

request.predicate = [NSPredicate predicateWithFormat:@"memberDeleted == %@", [NSNumber numberWithBool:NO]]; 

NSDictionary *properties = [entity propertiesByName]; 
request.propertiesToFetch = [NSArray arrayWithObject:[properties objectForKey:@"city"]]; 
request.returnsDistinctResults = YES; 
request.resultType = NSDictionaryResultType; 
request.fetchBatchSize = 20; 

NSError *error = nil; 
NSArray *tempArray = [self.managedObjectContext executeFetchRequest:request error:&error]; 

NSMutableArray *cities = [[NSMutableArray alloc] init]; 
for (int i=0; i < [tempArray count]; i++){ 
    NSDictionary *tempDict = [NSDictionary dictionary]; 
    tempDict = [tempArray objectAtIndex:i]; 

    if ([tempDict objectForKey:@"city"] != nil) 
     [cities addObject:[tempDict objectForKey:@"city"]]; 
} 

//if the tempArray has no nil values, it's more efficient with: 
//NSArray* cities = [tempArray valueForKeyPath:@"city"]; 

self.cityArray = cities; 
[cities release]; 
[request release]; 

Questo restituisce un NSArray con l'elenco delle città.

Grazie.

+1

Puoi farlo più facilmente. Basta fare questo: 'NSArray * cities = [tempArray valueForKeyPath: @" city "];' Questo otterrà il valore di 'city' per ogni dizionario nell'array e li metterà in un array. – Alex

+1

@Alex, che funziona bene se non c'è alcun valore nullo nella matrice. Se c'è qualche valore nullo, si blocca. –

+0

Oops. Ho svalutato il commento di "crash" di Rui mentre esaminavo questo problema, ritenendolo una valida precauzione. Ma il ref della classe NSArray elenca un metodo leggermente diverso, "valueForKey:", che dice restituirà un oggetto NSNull per oggetti nil. Quindi non dovrebbe esserci un problema. – Wienke

2

Dalla documentazione ufficiale:

NSManagedObjectContext *context = <#Get the context#>; 

NSEntityDescription *entity = [NSEntityDescription entityForName:@"<#Entity name#>" inManagedObjectContext:context]; 

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
[request setEntity:entity]; 
[request setResultType:NSDictionaryResultType]; 
[request setReturnsDistinctResults:YES]; 
[request setPropertiesToFetch :[NSArray arrayWithObject:@"<#Attribute name#>"]]; 

// Execute the fetch. 
NSError *error; 
id requestedValue = nil; 
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error]; 
if (objects == nil) { 
    // Handle the error. 
} 
Problemi correlati