2012-04-10 3 views
0

Ich habe eine Entität Tags, und ich möchte einen Abruf durchführen, um alle Tags zu erhalten und zu einem NSFetchedResultsController zuweisen. Aber ich möchte das erste Objekt in den abgerufenen Ergebnissen die Tag mit tagName Eigenschaft gleich "All" sein, dann der Rest nach alphabetischer Reihenfolge sortiert. Momentan mache ich das, was nur alle Tags in alphabetischer Reihenfolge zurückgibt, aber ich möchte, dass das Tag "All" immer zuerst heißt, dann der Rest in alphabetischer Reihenfolge.Anforderung mit mehreren Prädikaten abrufen?

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription 
            entityForName:@"Tag" inManagedObjectContext:appDelegate.managedObjectContext]; 

[fetchRequest setEntity:entity]; 
NSSortDescriptor *lastDescriptor = 
[[[NSSortDescriptor alloc] initWithKey:@"tagName"ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];  

[fetchRequest setSortDescriptors:[NSArray arrayWithObject:lastDescriptor]]; 
+0

können Sie die Methode localizedCaseInsensitiveCompare posten? Ich kann eine neue Lösung erstellen, aber ich denke, die beste Option ist es, Ihre tatsächliche Lösung zu optimieren. – ggrana

+0

Das ist nicht meine Methode..es ist nur eine Standardmethode, die gegeben ist – Snowman

Antwort

2

Sie benötigen einen Komparator von Ihnen erstellt verwenden, nicht ein Standard, so dass Sie so etwas tun:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription 
           entityForName:@"Tag" inManagedObjectContext:appDelegate.managedObjectContext]; 

[fetchRequest setEntity:entity]; 
NSSortDescriptor *lastDescriptor = 
[[[NSSortDescriptor alloc] initWithKey:@"tagName" ascending:YES comparator:^NSComparisonResult(NSString* tag1, NSString* tag2) { 

    if ([tag1 isEqualToString:@"All"]) return NSOrderedAscending; 
    if ([tag2 isEqualToString:@"All"]) return NSOrderedDescending; 

    return [tag1 compare:tag2]; 
}] autorelease];  

[fetchRequest setSortDescriptors:[NSArray arrayWithObject:lastDescriptor]]; 

bearbeiten

Wie @Andrew Madsen sagte, Sie können einen Komparator verwenden, ich sehe nicht, dass er bereits Ihre Frage beantwortet hat.

Sie auch einen Selektor verwenden kann, muß es nur in Ihrem Modell den Vergleich zu tun, ein Verfahren zu implementieren, was machte ich einen Fehler und glaubte, das war, was man tut, von Apfel doc:

Selektor

Verfahren zu verwenden, wenn die Eigenschaften von Objekten, beispielsweise caseInsensitiveCompare Vergleich: oder localizedCompare :. Der Selektor muss eine Methode angeben, die durch den Wert der Eigenschaft implementiert wird, die durch keyPath identifiziert wird. Der für den Vergleich verwendete Selektor wird als einzelner Parameter übergeben, das Objekt, das mit self verglichen werden soll, und muss die entsprechende NSComparisonResult-Konstante zurückgeben. Der Wähler muss haben die gleiche Methode Signatur wie: - (NSComparisonResult) localizedCompare: (NSString *) aString

+0

Ein sehr kleiner Nitpick, wenn Tag1 und Tag2 beide "Alle" sind, sollte der Vergleicher wahrscheinlich NSOrderedSame zurückgeben. Wahrscheinlich wird es aber in der Realität egal sein. –

+0

Ja, Sie haben recht, aber ich denke, dass dies für diesen speziellen Fall nicht relevant ist. – ggrana

+0

Eigentlich funktioniert das nicht richtig, wenn ich TagNames habe, die mit Zahlen beginnen. Wie kann der obige Code so bearbeitet werden, dass "All" sogar auf Tags mit Zahlen erscheint? – Snowman

1

Sie können dies mit NSSortDescriptor selbst mithilfe einer benutzerdefinierten Vergleichsmethode tun. Sie können die Ergebnisse der Abrufanforderung jedoch auch sortieren, nachdem Sie sie abgerufen haben. NSArray verfügt über eine Methode namens -sortedArrayUsingComparator:, mit der Sie das Array mithilfe eines Blocks sortieren können, wodurch benutzerdefiniertes Sortierverhalten wie dieses ziemlich einfach wird. Im folgenden sehen Sie ein Beispiel:

NSArray *sortedResults = [results sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
    NSString *tag1 = [obj1 tagName]; 
    NSString *tag2 = [obj2 tagName]; 

    BOOL tag1IsAll = [tag1 isEqualToString:@"All"]; 
    BOOL tag2IsAll = [tag2 isEqualToString:@"All"]; 
    if (tag1IsAll && !tag2IsAll) return NSOrderedAscending; 
    if (tag2IsAll && !tag1IsAll) return NSOrderedDescending; 

    return [tag1 compare:tag2]; 
}]; 
+0

Aber ich brauche es in einem NSFetchedResultsController zu sein, da ich ein UITableView verwende, und das wäre meine Datenquelle. – Snowman

+0

Kann ich diese Methode, die Sie in der Sortierungsdeskriptor-Auswahloption hinzugefügt haben, irgendwie anwenden? – Snowman

+0

Ja, tut mir leid. Ich habe nicht wirklich daran gedacht, dass Sie einen NSFetchedResultsController verwenden. Zu früh am Morgen für mich ;-). ggranas Antwort zeigt, wie Sie dasselbe mit einem NSSortDescriptor machen können. –

Verwandte Themen