使用transient属性排序UITableView节 [英] Order UITableView sections using a transient attribute
问题描述
我之前已发布过类似的问题,请查看此链接 UITableView节未按预期排序
我需要解决的问题如下:
我有一个带有自定义节的tableView。段标题取自在名为ToDoItem的NSManagegObject子类定义的瞬态属性。 transient属性称为sectionIdentifier。在我的tableView viewController我有一个fetchedResultsController与两个NSSortDescriptors命令对象:
I have published a similar question before, please take a look at this link UITableView sections are not ordered as expected The problem I need to resolve is following: I have a tableView with customised sections. The section titles are taken from a transient attribute defined at a NSManagegObject subclass called ToDoItem. The transient attribute is called sectionIdentifier. In my tableView viewController I have a fetchedResultsController with two NSSortDescriptors to order the objects:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"todoDueDate" ascending:YES];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:@"todoName" ascending:YES];
考虑到瞬态属性不能用作NSSortDescriptor处的initWithKey值,现在根据todoDueDate的属性值而不是由sectionIdentifier值排序,这应该是我的预期顺序。
我把下面的代码形式两个classer,第一个定义sectionIdentifier我的ToDoItem类和第二个tableView vieController类。
Taking into account that a transient attribute can't be used as initWithKey value at a NSSortDescriptor, the sections are ordered now depending on the attribute value for todoDueDate and not by the sectionIdentifier value, which should be my expected order. I put below the code form both classer, first definition of sectionIdentifier i the ToDoItem class and second the tableView vieController class.
-(NSString *)sectionIdentifier{
[self willAccessValueForKey:@"sectionIdentifier"];
NSString *tmp = [self primitiveValueForKey:@"sectionIdentifier"];
[self didAccessValueForKey:@"sectionIdentifier"];
if ([self.isSomeDay isEqualToString:@"noissomeday"]){//SI NO ES SOMEDAY
if (!tmp){
//NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger comps = (NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit);
NSDate *today = [NSDate date];
NSDate *date = self.todoDueDate;
NSDateComponents *date1Components = [calendar components:comps
fromDate: today];
NSDateComponents *date2Components = [calendar components:comps
fromDate: date];
today = [calendar dateFromComponents:date1Components];
date = [calendar dateFromComponents:date2Components];
NSInteger daysAfterToday = [calendar components:NSDayCalendarUnit
fromDate:today toDate:date options:0].day;
// NSString *section;
if (daysAfterToday < 0) {
tmp = @"0";
} else if (daysAfterToday == 0) {
tmp = @"1";
} else if (daysAfterToday > 0 && daysAfterToday < 2) {
tmp = @"2";
} else {
tmp = @"3";
}
NSLog(@"TODAY = %@", today);
NSLog(@"DATE = %@", date);
NSLog(@"DAYS AFTER TODAY = %ld",(long)daysAfterToday);
[self setPrimitiveValue:tmp forKey:@"sectionIdentifier"];
}
}
//no is someday
else if ([self.isSomeDay isEqualToString:@"issomeday"]){
tmp = @"4";
}
NSLog(@"Tmp= %@",tmp);
return tmp;
}
这是我想获取的节序:
1. OVERDUE, sectionIdentifier = 0
2. TODAY, sectionIdentifier = 1
3. TOMORROW, sectionIdentifier = 2
4. UPCOMING, sectionIdentifier = 3
5. SOMEDAY, sectionIdentifier = 4
ToDoItemsTableViewController.m
ToDoItemsTableViewController.m
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return 1;
}
else
{
return [[self.fetchedResultsController sections]count];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}
else {
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
ToDoItem *toDoItem = nil;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
}
NSLog(@"Configuring cell to show search results");
toDoItem = [self.searchResults objectAtIndex:indexPath.row];
cell.textLabel.text = toDoItem.todoName;
NSDate *fechaToDO = toDoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:@"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
NSString *valorSomeDay = toDoItem.isSomeDay;
if ([valorSomeDay isEqualToString:@"issomeday"]){
cell.detailTextLabel.text = @"Someday";
}
else {
cell.detailTextLabel.text = fechaToDo;
}
}
else
{
ToDoItem *todoitem = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = todoitem.todoName;
NSDate *fechaToDO = todoitem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:@"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
NSString *valorSomeDay = todoitem.isSomeDay;
if ([valorSomeDay isEqualToString:@"issomeday"]){
cell.detailTextLabel.text = @"Someday";
}
else {
cell.detailTextLabel.text = fechaToDo;
}
}
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *header = @"customHeader";
UITableViewHeaderFooterView *vHeader;
vHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:header];
if (!vHeader) {
vHeader = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:header];
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
if (section == 0) {
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
else if (section == 1) {
vHeader.textLabel.backgroundColor = [UIColor orangeColor];
vHeader.textLabel.textColor = [UIColor blueColor];
vHeader.contentView.backgroundColor = [UIColor orangeColor];
}
else if (section == 2) {
vHeader.textLabel.backgroundColor = [UIColor greenColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor greenColor];
}
else if (section == 3) {
vHeader.textLabel.backgroundColor = [UIColor greenColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor greenColor];
}
else if (section == 4) {
vHeader.textLabel.backgroundColor = [UIColor blueColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor blueColor];
}
vHeader.textLabel.text = [self tableView:tableView titleForHeaderInSection:section];
return vHeader;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if (tableView == self.searchDisplayController.searchResultsTableView){
NSString *valor = [NSString stringWithFormat:@"S E A R C H R E S U L T S (%d)",[self.searchResults count]];
return valor;
}
else {
id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections]objectAtIndex:section];
NSString *sectionname = [theSection name];
if ([sectionname isEqualToString:@"0"]){
NSString *valor = [NSString stringWithFormat:@"O V E R D U E (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:@"1"]){
NSString *valor = [NSString stringWithFormat:@"T O D A Y (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:@"2"]){
NSString *valor = [NSString stringWithFormat:@"T O M O R R O W (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:@"3"]){
NSString *valor = [NSString stringWithFormat:@"U P C O M I N G (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:@"4"]){
NSString *valor = [NSString stringWithFormat:@"S O M E D A Y (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
if ([[self.fetchedResultsController sections]count]>0){
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo name];
}
else{
return nil;
}
}
}
#pragma mark - Fetched Results Controller Section
-(NSFetchedResultsController*)fetchedResultsController{
if (_fetchedResultsController != nil){
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSManagedObjectContext *context = self.managedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ToDoItem" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"todoDueDate" ascending:YES];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:@"todoName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor,sortDescriptor1, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"sectionIdentifier" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
推荐答案
我假设SOMEDAY 条目是 todoDueDate
是unspecified的条目。
问题是第一个排序描述符todoDueDate必须与
节标识符兼容。因此,对于节,您不能使用两个单独的属性 todoDueDate
和
isSomeDay
。
I assume that the "SOMEDAY" entries are those where the todoDueDate
is "unspecified".
The problem is that the first sort descriptor "todoDueDate" must be compatible with
the section identifier. So you cannot use two separate properties todoDueDate
and
isSomeDay
for the sections.
因此,不应使用单独的属性 isSomeDay
,您应该分配这些对象
a在未来很远的值: / p>
Therefore, instead of using a separate property isSomeDay
, you should assign those objects
a value that is far in the future:
self.todoDueDate = [NSDate distantFuture];
,以便在所有其他对象后自动排序。
然后你可以在 sectionIdentifier
方法中这样做:
so that they are automatically ordered after all other objects.
Then you can do something like this in the sectionIdentifier
method:
if ([self.todoDueDate isEqualToDate:[NSDate distantFuture]) {
tmp = @"4";
} else {
// ... your other checks for overdue, today, tomorrow, upcoming
}
在 viewForHeaderInSection
中,你不应该检查节号,
而不是节名称(0 ,1,...)。原因是一个段可能为空:
如果没有OVERDUE对象,则TODAY是段#0。
Also in viewForHeaderInSection
, you should not check for the section number,
but for the section name ("0", "1", ...). The reason is that a section may be empty:
If there are not "OVERDUE" objects, then "TODAY" is section #0.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections] objectAtIndex:section];
NSString *tmp = [theSection name];
if ([tmp isEqualToString:@"0"]) {
// OVERDUE
} else if ([tmp isEqualToString:@"1"]) {
// TODAY
} else
// and so on ...
}
这篇关于使用transient属性排序UITableView节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!