搜索栏实现无效

时间:2014-01-16 05:59:21

标签: ios core-data uisearchbar

我正在关注Tim Roadley教程http://timroadley.com/2012/03/05/core-data-basics-part-7-search-bars/尝试向我的项目添加搜索栏,但我在执行应用程序时收到异常。这是例外:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'.

这是我的代码,用教程代码更新。

#import "ToDoItemsTableViewController.h"
#import "AppDelegate.h"
#import "AddToDoItemViewController.h"
#import "ToDoSubItemsTableViewController.h"

@interface ToDoItemsTableViewController ()

@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 blackColor],NSForegroundColorAttributeName,
                                    [UIColor blackColor],NSBackgroundColorAttributeName,nil];
    self.navigationController.navigationBar.titleTextAttributes = textAttributes;



    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
{

    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 forIndexPath:indexPath];

    // Configure the cell...

    ToDoItem *toDoItem = nil;

    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        NSLog(@"Configuring cell to show search results");
        toDoItem = [self.searchResults objectAtIndex:indexPath.row];
    }
    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];
    }


    vHeader.textLabel.text = [self tableView:tableView titleForHeaderInSection:section];

    return vHeader;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{




    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:@"U P C O M I N G   (%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 YES;
}
*/


// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        NSManagedObjectContext *context = [self managedObjectContext];
        ToDoItem *ToDoItemToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
        [context deleteObject:ToDoItemToDelete];


        NSError *error = nil;
        if (![context save:&error]){
            NSLog(@"Error: %@",error);
        }

    }
}


/*
// 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
{
    NSLog(@"Previous Search Results were removed.");
    [self.searchResults removeAllObjects];

    for (ToDoItem *toDoItem in [self.fetchedResultsController fetchedObjects])
    {
        if ([scope isEqualToString:@"All"] || [toDoItem.todoName isEqualToString:scope])
        {
            NSComparisonResult result = [toDoItem.todoName compare:searchText
                                                   options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
                                                     range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame)
            {
                NSLog(@"Adding toDoItem.todoName '%@' to searchResults as it begins with search text '%@'", toDoItem.todoName, searchText);
                [self.searchResults addObject:toDoItem];
            }
        }
    }
}
#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;
}

@end

欢迎任何建议或帮助。

1 个答案:

答案 0 :(得分:1)

尝试以这种方式纠正您的代码:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
你应该注意到:

  

重要说明:您必须使用以下命令注册类或nib文件   registerNib:forCellReuseIdentifier:或   registerClass:forCellReuseIdentifier:调用它之前的方法   方法

这是另一种方法:

   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

请参阅文档:https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableView/dequeueReusableCellWithIdentifier%3a