导航应用中的tableview排序按钮

时间:2012-03-11 23:36:18

标签: iphone objective-c uitableview core-data nsfetchedresultscontroller

我目前正在创建一个应用程序,根据不同的标准对团队进行排名,我希望用户可以根据这些不同的标准在表格视图中对团队进行排序。我在我的应用程序中使用核心数据来存储我的团队,并使用基于导航的模板,该模板首先向用户显示一个表格视图,并选择单击每个单元格来编辑团队。我想要做的一个例子是,Errands应用程序如何让您按截止日期,优先级,字母和手动对任务进行排序。

我尝试创建调用要更改的方法的按钮,sortDescriptor键,但我每次都要重新创建fetchedResultsController以进行更新(即不检查fetchedResultsController_!= nil),并且似乎要复制将位置改变到新位置而不是将其移动到那里的单元格。

我应该如何编写一个排序按钮,让用户更改表格的排序标准并正确更新表格?我已经阅读了很多关于fetchResultsController和NSSortDescriptors的帖子,但解决方案似乎是一次性的交易。

我可以真正使用一些帮助,或者参考一个教程来说明如何执行此操作。

这是我的RootViewController.m:

#import "RootViewController.h"
#import "TeamViewController.h"


@interface RootViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;

@end


@implementation RootViewController

@synthesize fetchedResultsController=fetchedResultsController_;
@synthesize managedObjectContext=managedObjectContext_;
@synthesize sortParam;
//@synthesize sortDescriptors;


#pragma mark -
#pragma mark View lifecycle

- (void)viewDidLoad {
    NSLog(@"viewDidLoad called");
    sortParam = @"totalRank";

    [super viewDidLoad];

    self.title = @"Title";

    // Set up the edit and add buttons.
    self.navigationItem.leftBarButtonItem = self.editButtonItem;

    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(showTeamView)];
    self.navigationItem.rightBarButtonItem = addButton;
    [addButton release];

    UIBarButtonItem* button1 = [[[UIBarButtonItem alloc] initWithTitle:@"Rank" style:UIBarButtonItemStyleBordered target:self action:@selector(reSort1:)] autorelease];

    UIBarButtonItem* button2 = [[[UIBarButtonItem alloc] initWithTitle:@"Name" style:UIBarButtonItemStyleBordered target:self action:@selector(reSort2:)] autorelease];

    [self setToolbarItems:[NSArray arrayWithObjects:button1, button2, nil]]; 

}

-(void)showTeamView {
    NSLog(@"showTeamView called");
    TeamViewController *teamViewController = [[TeamViewController alloc] initWithRootController:self team:nil];

    [self presentModalViewController:teamViewController animated:YES];
    [teamViewController release];
}


// Implement viewWillAppear: to do additional setup before the view is presented.
- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"viewWillAppear called");
//    sortParam = @"totalRank";
    [super viewWillAppear:animated];
}


- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"configureCell:atIndexPath called");
    NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
    NSString *textLabelText = [NSString stringWithFormat:@"%@ - %@", [[managedObject valueForKey:@"teamName"]description], [[managedObject valueForKey:@"teamNumber"]description]];
 //   NSLog(textLabelText);
    cell.textLabel.text = textLabelText;//[[managedObject valueForKey:@"teamName"] description];
    cell.detailTextLabel.text = [[managedObject valueForKey:@"totalRank"] description];
//  cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}

- (void)reSort1:(id)sender {
    NSLog(@"reSort1 called by: %@", sender);

    sortParam = @"totalRank";
    [self.tableView reloadData];
    [self viewDidLoad];


}

- (void)reSort2:(id)sender {
    NSLog(@"resort2 called by %@", sender);
    sortParam = @"teamName";
    [self.tableView reloadData];
    [self viewDidLoad];

}





#pragma mark -
#pragma mark Add a new object

-(void)insertTeamWithName:(NSString *)teamName teamNumber:(NSString *)teamNumber noteField:(NSString *)noteField driveTrain:(NSString *)driveTrain autoRank:(NSNumber *)autoRank offenseRank:(NSNumber *)offenseRank defenseRank:(NSNumber *)defenseRank speedRank:(NSNumber *)speedRank shooterRank:(NSNumber *)shooterRank totalRank:(NSNumber *)totalRank{

    // Create a new instance of the entity 
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
    NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

    // Configure the team
    [newManagedObject setValue:teamName forKey:@"teamName"];
    [newManagedObject setValue:teamNumber forKey:@"teamNumber"];        //new
    [newManagedObject setValue:noteField forKey:@"noteField"];
    [newManagedObject setValue:autoRank forKey:@"autoRank"];
    [newManagedObject setValue:driveTrain forKey:@"driveTrain"];
    [newManagedObject setValue:offenseRank forKey:@"offenseRank"];
    [newManagedObject setValue:defenseRank forKey:@"defenseRank"];
    [newManagedObject setValue:speedRank forKey:@"speedRank"];
    [newManagedObject setValue:shooterRank forKey:@"shooterRank"];

/*  [newManagedObject setValue:armRank forKey:@"armRank"];
    [newManagedObject setValue:speedRank forKey:@"speedRank"]; */
    [newManagedObject setValue:totalRank forKey:@"totalRank"];

    [self saveContext];
    NSLog(@"insertTeamWithNameCalled");
}


- (void)saveContext {

    // Create a new instance of the entity managed by the fetched results controller.
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];

    // Save the context.
    NSError *error = nil;
    if (![context save:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
         */
        NSLog(@"Unresolved error in saveContext %@, %@", error, [error userInfo]);
  //      abort();
    }
}


- (void)setEditing:(BOOL)editing animated:(BOOL)animated {

    // Prevent new objects being added when in editing mode.
    [super setEditing:(BOOL)editing animated:(BOOL)animated];
    self.navigationItem.rightBarButtonItem.enabled = !editing;
}


#pragma mark -
#pragma mark Table view data source
/*
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
}
*/
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [[self.fetchedResultsController sections] count];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"tableView:cellForRowAtIndexPath called");

    static NSString *CellIdentifier = @"TableCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell.
    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}



/*
// 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 YES;
}
*/


// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the managed object for the given index path
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
        [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];

        // Save the context.
        [self saveContext];
    }   
}


- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // The table view should not be re-orderable.
    return NO;
}




#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    NSManagedObject *team = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    TeamViewController *teamViewController = [[TeamViewController alloc] initWithRootController:self team:team];

    [self presentModalViewController:teamViewController animated:YES];
    [teamViewController release];
}


#pragma mark -
#pragma mark Fetched results controller

- (NSFetchedResultsController *)fetchedResultsController {

    NSLog(@"fetchResultsController called");
    /*
    if (fetchedResultsController_ != nil) {
        return fetchedResultsController_;
    }
    */
    /*
     Set up the fetched results controller.
    */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Team" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortParam ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    NSLog(@"sortParam == %@", sortParam);

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    NSError *error = nil;
    if (![fetchedResultsController_ performFetch:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
         */
        NSLog(@"Unresolved error in fetchedResultsController %@, %@", error, [error userInfo]);
     //   abort();
    }

    return fetchedResultsController_;
}    


#pragma mark -
#pragma mark Fetched results controller delegate


- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    NSLog(@"controllerWillChangeContent called");
    [self.tableView beginUpdates];
}


- (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;
    }

}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath {

    NSLog(@"controller:didChangeObject called");

    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:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    NSLog(@"controllerDidChangeContent called");
    [self.tableView endUpdates];
}


/*
// Implementing the above methods to update the table view in response to individual changes may have performance implications if a large number of changes are made simultaneously. If this proves to be an issue, you can instead just implement controllerDidChangeContent: which notifies the delegate that all section and object changes have been processed. 

 - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    // In the simplest, most efficient, case, reload the table view.
    [self.tableView reloadData];
}
 */


#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Relinquish ownership any cached data, images, etc that aren't in use.
}


- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
}


- (void)dealloc {
    [fetchedResultsController_ release];
    [managedObjectContext_ release];
 //   [sortParam release];
    [super dealloc];
}


@end

0 个答案:

没有答案