UITableView部分不按预期sorting

我正在使用自定义节标题的tableView。 核心数据对象根据来自称为sectionIdentifier的瞬态属性的值精确显示。 一切都如预期的那样工作,但是这些部分的顺序没有像我预期的那样响应。 这应该是部分顺序:

1. OVERDUE, sectionIdentifier = 0 2. TODAY, sectionIdentifier = 1 3. TOMORROW, sectionIdentifier = 2 4. UPCOMING, sectionIdentifier = 3 5. SOMEDAY, sectionIdentifier = 4 

在此应用程序状态下,部分顺序如下图所示: 在这里输入图像说明

欢迎任何帮助来解释这种行为,并find方式来获得所需的部分顺序。 这是我的代码,以帮助您find问题。

 #import "ToDoItemsTableViewController.h" #import "AppDelegate.h" #import "AddToDoItemViewController.h" #import "ToDoSubItemsTableViewController.h" @interface ToDoItemsTableViewController ()<UIAlertViewDelegate> @property (nonatomic, strong)NSManagedObjectContext *managedObjectContext; @property (nonatomic, strong)NSFetchedResultsController *fetchedResultsController; @end @implementation ToDoItemsTableViewController @synthesize searchResults; - (id)initWithStyle:(UITableViewStyle)style { self = [super initWithStyle:style]; if (self) { // Custom initialization } return self; } -(NSManagedObjectContext *)managedObjectContext{ return [(AppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext]; } - (void)viewDidLoad { [super viewDidLoad]; //navigation bar background image [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"navBar.png"] forBarMetrics:UIBarMetricsDefault]; NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys: [UIColor whiteColor],NSForegroundColorAttributeName, [UIColor whiteColor],NSBackgroundColorAttributeName,nil]; self.navigationController.navigationBar.titleTextAttributes = textAttributes; self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"navBar"]]; NSError *error = nil; if (![[self fetchedResultsController]performFetch:&error]){ NSLog(@"Error %@",error); abort(); } self.searchResults = [NSMutableArray arrayWithCapacity:[[self.fetchedResultsController fetchedObjects] count]]; [self.tableView reloadData]; } -(void) viewWillAppear:(BOOL)animated{ [self.tableView reloadData]; } - (void)viewDidUnload { self.searchResults = nil; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if ([[segue identifier]isEqualToString:@"addToDoItem"]){ UINavigationController *navigationController = segue.destinationViewController; AddToDoItemViewController *addToDoItemViewController = (AddToDoItemViewController*)navigationController.topViewController; ToDoItem *addToDoItem = [NSEntityDescription insertNewObjectForEntityForName:@"ToDoItem" inManagedObjectContext:self.managedObjectContext]; addToDoItem.todoDueDate = [NSDate date]; addToDoItemViewController.addToDoItem = addToDoItem; } if ([[segue identifier] isEqualToString:@"toToDoSubItems"]){ ToDoSubItemsTableViewController *todoSubItemsTableViewController = [segue destinationViewController]; NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; ToDoItem *selectedToDoItem = (ToDoItem*)[self.fetchedResultsController objectAtIndexPath:indexPath]; todoSubItemsTableViewController.selectedToDoItem = selectedToDoItem; } } #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]; 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]; 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:@"SEARCHRESULTS (%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:@"OVERDUE (%d)", [self.tableView numberOfRowsInSection:section]]; return valor; } else if ([sectionname isEqualToString:@"1"]){ NSString *valor = [NSString stringWithFormat:@"TODAY (%d)", [self.tableView numberOfRowsInSection:section]]; return valor; } else if ([sectionname isEqualToString:@"2"]){ NSString *valor = [NSString stringWithFormat:@"TOMORROW (%d)", [self.tableView numberOfRowsInSection:section]]; return valor; } else if ([sectionname isEqualToString:@"3"]){ NSString *valor = [NSString stringWithFormat:@"UPCOMING (%d)", [self.tableView numberOfRowsInSection:section]]; return valor; } else if ([sectionname isEqualToString:@"4"]){ NSString *valor = [NSString stringWithFormat:@"SOMEDAY (%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; } #pragma mark - Fetched Results Controller Delegates -(void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [self.tableView beginUpdates]; } -(void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; } -(void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{ UITableView *tableView = self.tableView; switch (type) { case NSFetchedResultsChangeInsert: [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate:{ ToDoItem *changeToDoItem = [self.fetchedResultsController objectAtIndexPath:indexPath]; UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.textLabel.text = changeToDoItem.todoName; NSDate *fechaToDO = changeToDoItem.todoDueDate; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init]; [dateFormatter setDateFormat:@"EEEE, dd MMMM YYYY"]; NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO]; cell.detailTextLabel.text = fechaToDo; } break; case NSFetchedResultsChangeMove: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } } -(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type{ switch (type) { case NSFetchedResultsChangeInsert: [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; } } // Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return NO; } // Override to support editing the table view. /* // Override to support rearranging the table view. - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { } */ /* // Override to support conditional rearranging of the table view. - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the item to be re-orderable. return YES; } */ /* #pragma mark - Navigation // In a story board-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ #pragma mark - #pragma mark Content Filtering -(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope { self.searchResults = [[self.fetchedResultsController fetchedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { ToDoItem * item = evaluatedObject; NSString* name = item.todoName; //searchText having length < 3 should not be considered if (!!searchText && [searchText length] < 3) { return YES; } if ([scope isEqualToString:@"All"] || [name isEqualToString:scope]) { return ([name rangeOfString:searchText].location != NSNotFound); } return NO; //if nothing matches }]]; } #pragma mark - #pragma mark UISearchDisplayController Delegate Methods - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { [self filterContentForSearchText:searchString scope:@"All"]; return YES; } - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption { [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:@"All"]; return YES; } - (IBAction)quickAddAction:(UIButton *)sender { UIAlertView * alert =[[UIAlertView alloc ] initWithTitle:@"Add Task" message:@"Enter the task name" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles: nil]; alert.alertViewStyle = UIAlertViewStylePlainTextInput; [alert addButtonWithTitle:@"Add"]; [alert show]; } - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { if (buttonIndex == 1) { UITextField *todoText = [alertView textFieldAtIndex:0]; NSLog(@"username: %@", todoText.text); ToDoItem *addToDoItem = [NSEntityDescription insertNewObjectForEntityForName:@"ToDoItem" inManagedObjectContext:self.managedObjectContext]; addToDoItem.todoDueDate = [NSDate date]; NSString *todoConvertido = todoText.text; addToDoItem.todoName = todoConvertido; [self.tableView reloadData]; } } @end 

您只根据截止date和名称进行sorting,因此具有最旧条目的类别排在第一位。

条目将不得不首先根据您的sectionIdentifier进行sorting

 NSSortDescriptor *sortDescriptor0 = [[NSSortDescriptor alloc]initWithKey:@"sectionIdentifier" ascending:YES]; NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:@"todoDueDate" ascending:YES]; NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc]initWithKey:@"todoName" ascending:YES];