0

Je rencontre des difficultés pour extraire les résultats des données de base triées par date.Récupération à partir des données de base triées par date formatée

J'ai une table DB qui contient des matchs de football. Chaque match a un homeTeam, un awayTeam et un kickoffTime. KickoffTime est un NSDate qui stocke la date et l'heure du début du match.

Je souhaite afficher les résultats d'une requête dans un TableView divisé en sections par la date de début. Avec la date comme en-tête de section.

Ceci est un peu plus complexe qu'il n'y paraît. En raison des fuseaux horaires différents, une correspondance commençant à une date dans une partie du monde commence réellement à une date différente dans une autre partie du monde. Donc, je ne peux pas simplement ignorer les temps et stocker les dates du coup d'envoi dans une autre colonne. Ce que j'essaie de faire créer un accesseur personnalisé qui renvoie une date formatée, quel que soit le fuseau horaire de l'utilisateur, puis l'utiliser pour trier et sectionner les résultats. Voici mon code dans Match.h:

@dynamic kickoffTime; 
@dynamic formattedKickoffTime; 
@dynamic dateFormatter; 

- (NSString *)formattedKickoffTime 
{ 
    [self willAccessValueForKey:@"kickoffTime"]; 

    // Set the date formatter to the format we want to display the date 
    [dateFormatter setDateFormat:@"ccc, d MMM"]; 

    // Format the date 
    NSString *myFormattedKickoffTime = [dateFormatter stringFromDate:[self kickoffTime]]; 

    [self didAccessValueForKey:@"kickoffTime"]; 

    // return the formatted date 
    return myFormattedKickoffTime; 
} 

- (NSDateFormatter *)dateFormatter 
{ 
    if (dateFormatter == nil) 
    { 
     dateFormatter = [[NSDateFormatter alloc] init]; 
    } 
    return dateFormatter; 
} 

@end 

Cependant lorsque je tente de chercher et trier les données comme ceci:

NSSortDescriptor *kickoffDescriptor = [[NSSortDescriptor alloc] initWithKey:@"formattedKickoffTime" ascending:YES]; 
... 
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:@"formattedKickoffTime" cacheName:nil]; 

je reçois le message d'erreur suivant:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath formattedKickoffTime not found in entity <NSSQLEntity Match id=1>' 

Would Quelqu'un offre des conseils s'il vous plaît?

Répondre

0

J'ai donc trouvé un moyen de le faire. Tout d'abord je garde toutes les dates et les calculs dans le modèle en GMT. J'ajoute un accesseur personnalisé (kickoffDate) à mon entité Match qui obtient le kickoffTime, met son heure à 00:00:00 et le retourne. Une chose que je devais faire, qui n'était pas évidente, était de régler le fuseau horaire de la date renvoyée par l'accesseur personnalisé à GMT, car sinon, il était réglé sur le système timeZone de l'utilisateur. Comme toutes les dates retournées par le modèle sont en GMT, tout semble fonctionner comme prévu, quel que soit le fuseau horaire que j'ai défini dans les paramètres de l'iPhone. Je suppose que Core Data est assez intelligent pour faire les ajustements timeZone avant de mettre les correspondances dans les sections.

J'ai une question cependant, est [NSTimeZone timeZoneForSecondsFromGMT:0] le meilleur moyen d'obtenir un fuseau horaire 0, par cela je veux dire un fuseau horaire qui n'est pas affecté par l'heure d'été?

Oh et dois-je appeler [self willAccessValueForKey:@"kickoffTime"]; et [self didAccessValueForKey:@"kickoffTime"];? Je ne comprends pas vraiment ce qu'ils font!

Voici le code dans Match.h:

... 
@dynamic homeTeam; 
@dynamic awayTeam; 
@dynamic kickoffTime; 

- (NSDate *)kickoffDate 
{ 
    [self willAccessValueForKey:@"kickoffTime"]; 
    NSCalendar *cal = [NSCalendar currentCalendar]; 
    NSDateComponents *components = [cal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:[self primitiveValueForKey:@"kickoffTime"]]; 
    [components setHour:0]; 
    [components setMinute:0]; 
    [components setSecond:0]; 
    [components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; 

    [self didAccessValueForKey:@"kickoffTime"]; 
    return [cal dateFromComponents:components]; 
} 

Et puis mon code comprend le chercher suivant une sorte sur kickoffTime et le sectionNameKeyPath est réglé sur kickoffDate:

NSSortDescriptor *kickoffDescriptor = [[NSSortDescriptor alloc] initWithKey:@"kickoffTime" ascending:YES]; 
... 
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:@"kickoffDate" cacheName:nil];