#uitableview #core-data #ios7 #nsfetchedresultscontroller
#uitableview #ядро-данные #ios7 #NSFetchedResultsController
Вопрос:
Я следую примеру от Apple, чтобы настроить свои разделы:
В настоящее время мои разделы отображаются в следующем порядке:
Section 0: "Upcoming"
Section 1: "Today"
Section 2: "Past"
Код, который я использую в своем NSManagedObject
файле .m:
#pragma mark - Transient properties
- (NSString *)sectionIdentifier
{
// Create and cache the section identifier on demand.
[self willAccessValueForKey:@"sectionIdentifier"];
NSString *tmp = [self primitiveSectionIdentifier];
[self didAccessValueForKey:@"sectionIdentifier"];
if (!tmp)
{
NSDate *dateToCompare = [self getUTCFormateDate:[self startDate]];
NSLog(@"********Date To Compare****** %@", dateToCompare);
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate* now = [NSDate date];
NSDateFormatter *format = [[NSDateFormatter alloc] init];
format.dateFormat = @"dd-MM-yyyy";
NSString *stringDate = [format stringFromDate:now];
NSDate *todaysDate = [format dateFromString:stringDate];
NSInteger differenceInDays =
[calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:dateToCompare] -
[calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:todaysDate];
NSString *sectionString;
if (differenceInDays == 0)
{
sectionString = kSectionIDToday;
}
else if (differenceInDays < 0)
{
sectionString = kSectionIDPast;
}
else if (differenceInDays > 0)
{
sectionString = kSectionIDUpcoming;
}
tmp = sectionString;
[self setPrimitiveSectionIdentifier:tmp];
}
return tmp;
}
-(NSDate *)getUTCFormateDate:(NSDate *)localDate
{
NSDateFormatter *dateFormatter;
if (!dateFormatter)
{
dateFormatter = [[NSDateFormatter alloc] init];
}
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:@"yyyy-MM-dd"];
NSString *dateString = [dateFormatter stringFromDate:localDate];
NSDate *dateFromString = [[NSDate alloc] init];
dateFromString = [dateFormatter dateFromString:dateString];
return dateFromString;
}
#pragma mark - Time stamp setter
- (void)setStartDate:(NSDate *)newDate
{
// If the time stamp changes, the section identifier become invalid.
[self willChangeValueForKey:@"startDate"];
[self setPrimitiveStartDate:newDate];
[self didChangeValueForKey:@"startDate"];
[self setPrimitiveSectionIdentifier:nil];
}
#pragma mark - Key path dependencies
(NSSet *)keyPathsForValuesAffectingSectionIdentifier
{
// If the value of timeStamp changes, the section identifier may change as well.
return [NSSet setWithObject:@"startDate"];
}
В моем TableViewController я настраиваю NSFetchedResults следующим образом:
- (NSFetchedResultsController *)fetchedResultsController
{
if(_fetchedResultsController!=nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *firstSort = [[NSSortDescriptor alloc] initWithKey:@"startDate"
ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:firstSort,nil];
[fetchRequest setSortDescriptors:sortDescriptors];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:@"sectionIdentifier"
cacheName:nil];
self.fetchedResultsController.delegate = self;
return self.fetchedResultsController;
}
Вопрос 1: Как мне заставить разделы отображаться в следующем порядке:
Section 0: Today
Section 1: Upcoming
Section 2: Past
Вопрос 2: Как мне сортировать строки в каждом разделе на основе атрибута, вызываемого "modified"
в каждом объекте?
Ответ №1:
Порядок разделов и строк на 100% зависит от дескрипторов сортировки. Вы хотите, чтобы ваш первый дескриптор сортировки сортировал все в соответствующий раздел, а затем ваши следующие дескрипторы сортировки сортировали строки внутри разделов.
Например, если вам нужны три раздела, основанные на «группе», а затем вы хотите, чтобы строки были отсортированы по имени внутри группы, вы бы добавили дескрипторы сортировки как:
NSArray *descriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"group" ascending:YES], [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
[fetchRequest setSortDescriptors:descriptors];
Ваш ключ раздела для вашего NSFetchedResultsController
также должен соответствовать вашему первому NSSortDescriptor
.
Комментарии:
1. Спасибо. Все объекты сортируются на основе вызываемого атрибута
startDate
. Как бы я заставилToday
раздел появляться раньшеUpcoming
. Нужно ли мне сначала создать другое вызываемое временное свойствоsortKey
и отсортировать его на основе этого?2. да, создайте новый ключ для сортировки вверху, чтобы поместить все в соответствующие разделы.
NSSortDescriptor
экземплярам требуются нестационарные свойства, поэтому вам нужно подумать об этой части вашего дизайна…3. Я, наконец, решил изменить модель и добавил
sortKey
. Но теперь я получаю другую ошибку:CoreData: error: (NSFetchedResultsController) The fetched object at index 3 has an out of order section name ' Past. Objects must be sorted by section name'
Я сделал пример проекта, который дублирует ошибку: github.com/KausiAhmed/FRC4. Ваша сортировка должна начинаться с вашей
sectionIdentifier
, а затем вы можете сортировать по чему-либо еще. Но первыйNSSortDescriptor
должен соответствоватьsectionNameKeyPath
.5. Спасибо, что взглянули на код! Я следил за кодом Apple, и он имеет
sectionIdentifier
transient
свойство и не сортируется на основеsectionNameKeyPath
: developer.apple.com/library/ios/samplecode/DateSectionTitles/… Должен ли я изменить его на свойство non-transient? Я думал, возможно, сделать отдельный FRC для каждого раздела?