UITableView部分未按预期排序 [英] UITableView sections are not ordered as expected

查看:47
本文介绍了UITableView部分未按预期排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用带有自定义节标题的tableView.核心数据对象显示在精确的部分上,具体取决于名为sectionIdentifier的瞬态属性中的值.一切都按预期工作,但各节的顺序没有按我预期的那样响应.这应该是各节的顺序:

I am using a tableView with customised section titles. The core data objects are shown on a precise section depending on the value from a transient attribute called sectionIdentifier. Everything is working as expected, but the order of the sections is not responding as I expected. This should be the sections order:

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

在此应用状态下,截面顺序如下图所示:

At this app state, the section order is as shown in the image below:

欢迎任何帮助来解释此行为并找到获取所需节顺序的方法.这是我的代码,可帮助您发现问题.

Any help is welcome to explain this behaviour and to find the way to obtain the desired section order. Here is my code to help you find the issue.

#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:@"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;
}


#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

推荐答案

您仅根据到期日期和名称进行排序,因此具有最早条目的类别排在首位.

you sort only based on due Date and name so the category with the oldest entry comes first.

必须首先根据您的sectionIdentifier对条目进行排序

the entries would have to be sorted based on your sectionIdentifier first

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

这篇关于UITableView部分未按预期排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆