2009-09-05 3 views
13

Sto creando una tabella sezionata con risultati recuperati, ma sto facendo fatica a trovare le sezioni personalizzate elaborate.Utilizzo di sezioni personalizzate con NSFetchedResultsController?

Normalmente uno avrebbe solo un attributo da ordinare e utilizzare sectionNameKeyPath: per generare le sezioni. Ma il mio attributo di ordinamento è calcolato al volo, e io non riesco a ottenere il fetchedResultsController di utilizzare correttamente ...

Aggiornamento: Utilizzando jbrennan 's consigli qui sotto, sono davvero vicino al previsto funzionalità. Ho aggiunto una categoria a NSDate che restituisce un numero "giorni fa"; mettendo che qui mi dà sezioni in base a quei numeri:

NSFetchedResultsController *aFetchedResultsController = 
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
    managedObjectContext:managedObjectContext 
    sectionNameKeyPath:@"myDateAttribute.daysAgo" 
    cacheName:@"Root"]; 

Ecco dove mi sono bloccato: non ho bisogno di loro ordinati per "giorni fa," Ho bisogno di loro ordinati tramite alcuni calcoli sulla base di altri attributi nell'entità. Quindi non posso che chiamare metodo personalizzato Categoria, ho bisogno di chiamare un metodo con argomenti, in questo modo:

[myDateAttribute sortingRoutine:thisObject.value] 

O qualcosa del genere. Spero che abbia un certo senso. Grazie mille se puoi aiutare :)

risposta

6

È possibile provare quanto segue.

Aggiungere un attributo transitorio al modello di dati di base nell'entità Operazione. Quindi implementare il metodo

nella classe Attività NSManagedObject. Vedi la sua documentazione. All'interno del metodo è possibile impostare un valore per la proprietà temporanea utilizzando i valori delle altre proprietà. Nota che ci sono alcune restrizioni su cosa puoi fare, ma questo è ben spiegato nella documentazione (in particolare non puoi modificare le relazioni o passare argomenti, tuttavia, se puoi calcolare la tua proprietà transitoria usando solo i valori delle altre proprietà/relazioni dovrebbe essere perfettamente bene).

Una volta fatto, si utilizza semplicemente la proprietà transiente come attributo che si passa per ottenere le sezioni.

+0

Aha! Questo ha funzionato magnificamente, grazie. Ora l'app si arresta in modo anomalo quando si salvano nuove attività, ma ci lavorerò sopra per un po 'e postare una domanda separata se necessario. :) – Triz

+0

L'app non dovrebbe arrestarsi in modo anomalo durante il salvataggio: le proprietà transitorie non vengono memorizzate, quindi questa non può essere la causa in alcun modo. –

+0

In realtà non si arresta in modo anomalo durante il processo di salvataggio, ma * dopo * it, quando la vista ritorna alla tabella in sezione. Non lo facevo prima di questi cambiamenti, e non ho fatto nient'altro, quindi penso che sia correlato. Forse 'awakeFromFetch:' non viene chiamato quando riappare la vista? – Triz

16

Ho fatto qualcosa di simile in un'app per iPhone (che presto sarà) in consegna. Le mie sezioni sono state suddivise in date come questa: Ieri, Oggi, Domani, In futuro ...

In ogni caso, il trucco per me era aggiungere una Categoria a NSDate per determinare in quale sezione apparteneva il mio oggetto recuperato.

Il mio oggetto gestito aveva una proprietà denominata dueDate, che era un NSDate. Durante la configurazione del controller dei risultati recuperati, ho utilizzato @"dueDate.relativeDate" come percorso chiave della sezione.

In Categoria, -relativeDate è stato dichiarato come la restituzione di un NSString e anche come una proprietà readonly (ciascuno dei quali potrebbe essere sufficiente, non ho provato senza avere entrambi, ma non fa male avere sia un metodo e proprietà dichiarazione). Quindi ho semplicemente implementato il metodo in modo efficace.

+0

Va bene, penso di essere con te.Cosa succede se i miei NSDate sono effettivamente in un'entità separata, però? Ho "Task" come le principali entità che vengono recuperate, e "Ripristini" sono correlati (a molti). Quindi ogni 'Task' ha una serie di date di' Reset', con il più recente è il più importante qui. Quello che ho provato era usare '@" reset.specialDateMethod' come chiave di ordinamento, ma non gli piace ... – Triz

+0

Dipende da cosa fa 'specialDateMethod'. In quel metodo, potresti probabilmente filtrare il tuo set di Resetta con un NSPredicate per trovare quello importante, e poi usa il suo 'date' come vuoi.Potresti anche voler memorizzare il' Reset' perché immagino che sarebbe costoso. Forse il tuo 'Task' potrebbe avere una proprietà come" mostRecentReset "o qualsiasi altra cosa rilevante – jbrennan

+0

Altro al punto: che cosa è' sectionNameKeyPath: 'che si aspetta? Deve essere una stringa, che corrisponde a un attributo nell'entità? Penso che questo sia il punto in cui sono confuso Aggiornamento – Triz

0

Ecco un mucchio di codice per ottenere questo (grazie jbrennan):

@implementation NSDate (MyExtensions) 


// Return today. 
+ (NSDate *)today { 

    return [NSDate date]; 
} 


// Return yesterday (today minus 24 hours). 
+ (NSDate *)yesterday { 

    return [NSDate dateWithTimeIntervalSinceNow:-60*60*24]; 
} 


// Return tomorrow (today plus 24 hours). 
+ (NSDate *)tomorrow { 

    return [NSDate dateWithTimeIntervalSinceNow:60*60*24]; 
} 


// Convert a date comporting a time into a rounded date (just the day, no time). 
- (NSDate *)dayDate { 

    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; 
    NSDateComponents *comps = [[NSCalendar currentCalendar] components:unitFlags fromDate:self]; 
    return [[NSCalendar currentCalendar] dateFromComponents:comps]; 
} 


// Return a string representing the date relatively (today, tomorrow, yesterday, etc.) 
// If no relative sentence is found, return the NSDateFormatterLongStyle formatted date. 
- (NSString *)relativeDate { 

    if ([self.dayDate isEqualToDate:[[NSDate today] dayDate]]) { 

     return NSLocalizedString(@"Today", @"NSDate extensions"); 
    } 
    if ([self.dayDate isEqualToDate:[[NSDate yesterday] dayDate]]) { 

     return NSLocalizedString(@"Yesterday", @"NSDate extensions"); 
    } 
    if ([self.dayDate isEqualToDate:[[NSDate tomorrow] dayDate]]) { 

     return NSLocalizedString(@"Tomorrow", @"NSDate extensions"); 
    } 

    return [NSDateFormatter localizedStringFromDate:self 
              dateStyle:NSDateFormatterLongStyle 
              timeStyle:NSDateFormatterNoStyle];  
} 


@end 
+1

Questo è vecchio, ma chiunque legga questo: NON usare costanti di secondi come questo, usa le funzioni di NSCalendar. Vai a vedere qualsiasi discorso sul WWDC in date –