Desidero fornire un ordinamento personalizzato utilizzando NSFetchedResultsController e NSSortDescriptor.Ordinamento personalizzato con NSFetchedResultController (sottoclasse NSSortDescriptor)
Come ordinamento personalizzato tramite messaggio NSSortDescriptor - (id) initWithKey: in ordine crescente: selettore: non è possibile (vedi here), ho cercato di usare una classe derivata NSSortDescriptor al fine di ignorare il compareObject: ToObject: messaggio.
Il mio problema è che compareObject: toObject: non viene sempre chiamato. Sembra che sia chiamato solo quando i dati sono già in memoria. Esiste un'ottimizzazione di qualche tipo che utilizza un ordinamento basato su database invece di compareObject: toObject quando i dati vengono recuperati dal negozio la prima volta. (vedi here).
La mia domanda è: come forzare NSFetchedResultscontroller per utilizzare il confrontoObject: toObject: messaggio per ordinare i dati? (e funzionerà con un grande set di dati)
Una soluzione è utilizzare un archivio binario invece di un negozio SQLite, ma non voglio farlo.
Un'altra soluzione è:
-call performFetch per ordinare i dati tramite SQL (compareObject non chiamato)
-fare una modifica ai dati e invertirla.
-call Eseguire nuovamente il recupero (compareOggetto è chiamato)
Funziona nel mio caso ma è un trucco e non sono sicuro che funzionerà sempre (soprattutto con un set di dati di grandi dimensioni (maggiore della dimensione del batch)).
AGGIORNATO: È possibile riprodurre con l'esempio CoreDataBooks.
In RootViewController.m, aggiungere questo brutto hack:
- (void)viewWillAppear:(BOOL)animated {
Book* book = (Book *)[NSEntityDescription insertNewObjectForEntityForName:@"Book"
inManagedObjectContext:[self fetchedResultsController].managedObjectContext];
[[self fetchedResultsController] performFetch:nil];
[[self fetchedResultsController].managedObjectContext deleteObject:book];
[self.tableView reloadData];
}
In RootViewController.m, sostituire il codice descrittore tipo con:
MySortDescriptor *myDescriptor = [[MySortDescriptor alloc] init];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:myDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
Aggiungi classe MySortDescriptor:
@implementation MySortDescriptor
-(id)init
{
if (self = [super initWithKey:@"title" ascending:YES selector:@selector(compare:)])
{
}
return self;
}
- (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2
{
//set a breakpoint here
return [[object1 valueForKey:@"author" ] localizedCaseInsensitiveCompare:[object2 valueForKey:@"author" ] ];
}
//various overrides inspired by [this blog post][3]
- (id)copy
{
return [self copyWithZone:nil ];
}
- (id)mutableCopy
{
return [self copyWithZone:nil ];
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return [self copyWithZone:zone ];
}
- (id)copyWithZone:(NSZone*)zone
{
return [[MySortDescriptor alloc] initWithKey:[self key] ascending:[self ascending] selector:[self selector]];
}
- (id)reversedSortDescriptor
{
return [[[MySortDescriptor alloc] initWithKey:[self key] ascending:![self ascending] selector:[self selector]] autorelease];
}
@end
Come si sta tentando di ordinare i dati che NSSortDescriptor o una combinazione di più NSSortDescriptors è insufficiente? – ImHuntingWabbits
Sto cercando di ordinare i punti in base alla loro distanza da un punto di riferimento. Speravo di incapsulare il punto di riferimento come un ivar in un oggetto derivato NSSortDescriptor. – FKDev
Hmm, sembra un problema interessante. Sicuramente sembra che dovrai mettere gli oggetti in memoria per ordinarli. Potresti avere una proprietà "referencePoint" sulla tua entità target e una proprietà transitoria chiamata distance. Implementare la distanza per calcolare la distanza tra il punto di riferimento e l'entità di destinazione, ordinare sulla distanza. Anche se mi piace di più la tua idea di sottoclasse. – ImHuntingWabbits