Группировка по рабочим дням с основными данными - PullRequest
2 голосов
/ 11 августа 2009

В моей базовой модели данных у меня есть объект с атрибутом даты, и, как следует из заголовка, я бы хотел сгруппировать этот объект по (недельным) дням.

Проблема в том, что даты хранятся более или менее как метки времени, и я не знаю, как создать предикат, способный соответствующим образом группировать / фильтровать мои объекты.

Я понял, что мне, вероятно, придется делать выборку для каждого дня, поэтому создал следующий метод. Код, с которым мне нужна помощь, находится прямо посередине.

- (NSFetchedResultsController *)fetchedResultsController:(NSDate *)day  {
if(fetchedResultsController != nil)
    return fetchedResultsController;

// Create and Configure Request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[request setEntity:entity];

// Predicate
// pseudo code where i'm clueless is marked by "<" and ">" - start
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"DateAttribute BETWEEN <first second of day> AND <last second of day>"];
// or
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"<dayofmonth-month-year of DateAttribute> LIKE <dayofmonth-month-year of day>"];
[request setPredicate:predicate];
// pseudo code where i'm clueless is marked by "<" and ">" - end

// Sort descriptors
NSSortDescriptor *titleDescriptor = [[NSSortDescriptor alloc] initWithKey:sortDescriptorName ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:titleDescriptor];
[request setSortDescriptors:sortDescriptors]; 

// create and init fetchResultsController
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
self.fetchedResultsController = aFetchedResultsController;
fetchedResultsController.delegate = self;

//Memory
[request release];
[titleDescriptor release];
[aFetchedResultsController release];

return fetchedResultsController;

}

Я бы очень признателен за любую помощь. Спасибо

Ответы [ 2 ]

6 голосов
/ 11 августа 2009

Если вы хотите сгруппировать по дням недели, проще всего добавить в вашу сущность атрибут типа «будний день»; затем вы передаете "weekday" в качестве аргумента sectionNameKeyPath при инициализации NSFetchedResultsController. В этом случае указывать предикат не нужно: вы автоматически получите разделы для рабочих дней.

Если вы хотите группировать по дням, вы передаете DateAttribute в качестве аргумента sectionNameKeyPath при инициализации NSFetchedResultsController. Опять же, нет необходимости указывать предикат: вы автоматически получите разделы для дней.

То, что вы пытаетесь сделать в своем коде, отличается от того, что вы просили. Действительно, вы не пытаетесь вернуть разделы (то есть группировать по атрибуту): вместо этого вы пытаетесь вернуть один раздел для вашего tableView, содержащий объекты, описываемые вашей сущностью, удовлетворяющие конкретному предикату, а именно те, чей DateAttribute падает (вероятно ) в текущий день. Для этого вы можете использовать следующий код:

// start by retrieving day, weekday, month and year components for today
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todayComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]];
NSInteger theDay = [todayComponents day];
NSInteger theMonth = [todayComponents month];
NSInteger theYear = [todayComponents year];

// now build a NSDate object for the input date using these components
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:theDay]; 
[components setMonth:theMonth]; 
[components setYear:theYear];
NSDate *thisDate = [gregorian dateFromComponents:components];
[components release];


// now build a NSDate object for tomorrow
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:1];
NSDate *nextDate = [gregorian dateByAddingComponents:offsetComponents toDate:thisDate options:0];
[offsetComponents release];

NSDateComponents *tomorrowComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:nextDate];
NSInteger tomorrowDay = [tomorrowComponents day];
NSInteger tomorrowMonth = [tomorrowComponents month];
NSInteger tomorrowYear = [tomorrowComponents year];

[gregorian release];


// now build the predicate needed to fetch the information
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"DateAttribute < %@ && DateAttribute > %@", nextDate, thisDate];

Этот предикат будет извлекать ровно все объекты, атрибут DateAttribute которых относится к текущему дню. Надеюсь, это поможет.

4 голосов
/ 27 сентября 2010

Привет @gabtub Я на самом деле смотрел на ваш вопрос, и у меня был такой же вопрос. Я хотел разделить мою таблицу на разделы по дате, а не по метке времени, как вы уже упоминали. Итак, я добавил новый метод в моем классе, который расширяет NSManagedObject (который является сущностью, которую я выбираю), этот метод возвращает форматированную дату как таковую:

- (NSString *)transactionDay{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
return [dateFormatter stringFromDate:self.date];}

затем изменил мой fetchedResultController на:

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"transactionDay" cacheName:nil];

И все заработало как шарм.

Проверьте ссылку, чтобы увидеть более подробную информацию. http://www.IPHONE4GAPP.NET/superdb-core-data-app-with-sections.html

...