2009-07-01 11 views
19

Le Core Data Documentation stabilisce che:come ordinare Core Data proprietà recuperati

La Fetch richiesta associata con la [inverosimile] proprietà può avere un ordinamento sorta, e, quindi, la proprietà inverosimile può essere ordinato.

Come specificare i descrittori di ordinamento per la proprietà recuperata nell'editor del modello dati Xcode? Non riesco a trovare un campo pertinente ovunque. Sto sviluppando per la piattaforma iPhone, se questo fa alcuna differenza.

Se ciò non è possibile tramite l'editor del modello grafico, come posso modificare la richiesta di recupero per la proprietà recuperata nel codice in modo che abbia un descrittore di ordinamento?

+0

aggiungi il tag iphone – Dan

risposta

5

Lo strumento di modellazione non sembra avere un modo per impostare i descrittori di ordinamento sulla richiesta di recupero.

Dovrebbe essere possibile [1], dopo aver caricato il modello ma prima di associarlo a un coordinatore di archivio permanente, trovare le descrizioni delle proprietà recuperate per le quali si desidera controllare l'ordinamento e sostituire le richieste di recupero con il recupero richiede che siano presenti dei descrittori di ordinamento.

[1] In linea di principio questo dovrebbe funzionare. In pratica, non l'ho ancora fatto o testato.

+1

È un peccato che lo strumento di modellazione non abbia questa caratteristica - sembra che diminuisca in gran parte l'utilità di poter specificare richieste di recupero nello strumento. –

+0

Questa domanda fornisce un esempio di creazione di programmazione una NSFetchedPropertyDescription e aggiungendolo a un NSManagedObjectModel: http://stackoverflow.com/questions/5638364/how-do-i-create-an-nsfetchedpropertydescription-programmatically –

13

Non li si specifica nell'editor grafico (per quanto ne so).

Si specificano nel codice in cui si effettua il recupero.

NSFetchRequest* request = [[NSFetchRequest alloc] init]; 
NSEntityDescription* entity = [NSEntityDescription entityForName:@"whatYouAreLookingFor" 
    inManagedObjectContext:self.managedObjectContext]; 
[request setEntity:entity]; 

// here's where you specify the sort 
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] 
           initWithKey:@"name" ascending:YES]; 
NSArray* sortDescriptors = [[[NSArray alloc] initWithObjects: sortDescriptor, nil] autorelease]; 
[request setSortDescriptors:sortDescriptors]; 
[sortDescriptor release]; 

fetchedResultsController = [[NSFetchedResultsController alloc] 
       initWithFetchRequest:request 
       managedObjectContext:self.managedObjectContext 
       sectionNameKeyPath:nil 
          cacheName:@"myCache"]; 
+0

Questo è giusto sopra. Devi aggiungere NSSortDescriptor che non puoi specificare nel tuo datamodel scusa. Sì, è a lungo senza fiato, ma questo è esattamente ciò che sto facendo nella mia app dati principale. –

+25

Quanto sopra va bene per una normale richiesta di recupero ma non ha nulla a che fare con la domanda, che riguarda le proprietà recuperate e il loro ordinamento. – Hunter

0

Purtroppo, tuttavia, la possibilità di ordinare è alquanto limitata. Ad esempio, non puoi prendere un campo che è un NSString contenente un numero e ordinarlo numericamente, almeno non con un archivio di supporto SQLite. Finché si ordina in ordine alfabetico sulle stringhe, numericamente solo sui valori memorizzati come numeri e così via, tuttavia, il NSSortDescriptor applicato alla richiesta di recupero funziona correttamente.

+1

È possibile scrivere metodi di ordinamento più sofisticati, utilizzando initWithKey di NSSortDescriptor: crescente: selettore: –

35

Si può effettivamente prendere la proprietà del modello recuperato e aggiungere i descrittori di ordinamento (di nuovo, nel codice). Ho fatto questo nel metodo standard che XCode genera nel tuo AppDelegate se scegli uno dei modelli con Core Data:

A proposito. Ordina TUTTE le proprietà recuperate su TUTTI i modelli nel tuo modello dati. Si poteva essere fantasiosi e adattivi con esso, ma era il modo più succinto di gestire l'ordinamento dei 7 modelli separati che ciascuno aveva proprietà recuperate che dovevano essere ordinate per nome. Funziona bene.

/** 
Returns the managed object model for the application. 
If the model doesn't already exist, it is created by merging all of the models found in the application bundle. 
*/ 
- (NSManagedObjectModel *)managedObjectModel { 

    if (managedObjectModel != nil) { 
     return managedObjectModel; 
    } 
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];  

    // Find the fetched properties, and make them sorted... 
    for (NSEntityDescription *entity in [managedObjectModel entities]) { 
     for (NSPropertyDescription *property in [entity properties]) { 
      if ([property isKindOfClass:[NSFetchedPropertyDescription class]]) { 
       NSFetchedPropertyDescription *fetchedProperty = (NSFetchedPropertyDescription *)property; 
       NSFetchRequest *fetchRequest = [fetchedProperty fetchRequest]; 

       // Only sort by name if the destination entity actually has a "name" field 
       if ([[[[fetchRequest entity] propertiesByName] allKeys] containsObject:@"name"]) { 
        NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
        [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]]; 
        [sortByName release]; 
       } 
      } 
     } 
    } 

    return managedObjectModel; 
} 
+5

Inoltre, anche la codifica del valore chiave può essere di aiuto, ad esempio: \t [managedObjectModel setValue: sortDescriptorArray forKeyPath: @ "entitiesByName.EntityName.propertiesByName. fetchPropertyName.fetchRequest.sortDescriptors "]; –

-1

Jeff, se le stringhe sono allineate a destra, è possibile ordinare le stringhe; "123"> "23" e così via. Ma lo spazio di iirc ascii è dopo i numeri e, in tal caso, ciò che si farebbe è creare una proprietà dinamica che sia NSNumber (che supporta il metodo compare:), e utilizzare il metodo numberFromString: per creare un numero dalla stringa. Quindi è possibile specificare il campo numerico nell'ordinamento. Nell'interfaccia:

@property NSString *stringIsaNumber; // in the data model 
@property NSNumber *number; 

nell'attuazione:

@dynamic stringIsaNumber; 
- (NSNumber *) number ; 
{ return [self.stringIsaNumber numberFromString]; } 
- (void) setNumber:(NSNumber *)value; 
{ self.stringIsaNumber = [NSString stringWithFormat:@"%5i",value) } 

ps plz perdona errori di codifica, questo è fuori della parte superiore della mia testa.

5

Utilizzando grande risposta di Tim Shadel ho aggiunto per-NSManagedObject sottoclasse di smistamento ...

... in Tier.m (che è una sottoclasse NSManagedObject) ...

+ (void)initialize 
{ 
    if(self == [Tier class]) 
    { 
     NSFetchedPropertyDescription *displayLessonPropertyDescription = [[[Tier entityDescription] propertiesByName] objectForKey:@"displayLesson"]; 
     NSFetchRequest *fetchRequest = [displayLessonPropertyDescription fetchRequest]; 

     NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"displayOrder" ascending:YES]; 
     [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]]; 
     [sortByName release]; 
    } 
} 
+1

Dove è definito - [EntitàDistribuzione di livello] ?! – hatfinch

+0

Ah, sto usando RestKit in questa situazione che ha un sacco di metodi convenienti come quello. Controlla la loro categoria NSManagedObject + ActiveRecord. – rob5408

+0

Non sono sicuro del motivo per cui la modifica di @ AndyOS è stata rifiutata, ho sicuramente avuto un errore nel mio codice. – rob5408

0

mettere questo in il vostro NSManagedObject sottoclasse:

+ (void)initialize 
{ 
    if (self != [EntityManagedObjectSubClass class]) return; 
    NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; 
    NSEntityDescription *entityDescription = [managedObjectModel entitiesByName][@"entityName"]; 
    NSFetchedPropertyDescription *fetchedPropertyDescription = [entityDescription propertiesByName][@"fetchedPropertyName"]; 
    NSFetchRequest *fetchRequest = [fetchedPropertyDescription fetchRequest]; 
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sortDescriptorKey" ascending:YES]; 
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
} 

Sostituire EntityManagedObjectSubClass, entityName, fetchedPropertyName e sortDescriptorKey con yo le tue stesse cose