ios - 删除部分的最后一行后,应用程序崩溃

标签 ios uitableview core-data

在我的 iOS 应用程序中,我有一个包含部分的表格 View ,全部由核心数据填充。 如果删除某个部分的最后一行,应用程序将崩溃。 我无法找出我的代码中的问题出在哪里,恳请您帮助我。先感谢您。这是到目前为止我的代码:

#import "PersonsTVC.h"
#import "Person.h"

@implementation PersonsTVC
@synthesize fetchedResultsController = __fetchedResultsController;
@synthesize managedObjectContext = __managedObjectContext;
@synthesize selectedPerson;
@synthesize searchResults,titulosseccion;



- (void)setupFetchedResultsController
{
    // 1 - Decide what Entity you want
    NSString *entityName = @"Person"; // Put your entity name here
    NSLog(@"Setting up a Fetched Results Controller for the Entity named %@", entityName);

    // 2 - Request that Entity
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];

    // 3 - Filter it if you want
    //request.predicate = [NSPredicate predicateWithFormat:@"Person.name = Blah"];

    // 4 - Sort it if you want
    // First sort descriptor (required for grouping into sections):
    NSSortDescriptor *sortByDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
    // Second sort descriptor (for the items within each section):
    NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"firstname" ascending:YES];
    [request setSortDescriptors:@[sortByDate, sortByName]];


   //
   // request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"firstname"
                                                                                     //ascending:YES
                                                                                      //selector:@selector(localizedCaseInsensitiveCompare:)]];
    // 5 - Fetch it
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                        managedObjectContext:self.managedObjectContext
                                                                          sectionNameKeyPath:@"sectionIdentifier"
                                                                                   cacheName:nil];
    [self performFetch];
}




- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections] objectAtIndex:section];

    NSString *sectionName = [theSection name];
    if ([sectionName isEqualToString:@"0"]) {
        return @"Today";
    } else if ([sectionName isEqualToString:@"1"]) {
        return @"Tomorrow";
    }
    else if ([sectionName isEqualToString:@"2"]) {
        return @"Upcoming";
    }
    return @"Other";
}

- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.

    return [[self.fetchedResultsController sections] count];
}



- (void) viewDidLoad
{



    self.searchResults = [NSMutableArray arrayWithCapacity:[[self.fetchedResultsController fetchedObjects] count]];
    [self.tableView reloadData];
}








- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self setupFetchedResultsController];
}




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

    // Perform segue to detail when a SEARCH table cell is touched
    if(tableView == self.searchDisplayController.searchResultsTableView)
    {
        [self performSegueWithIdentifier:@"Person Detail Segue" sender:tableView];
    }

}



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Persons Cell";

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

    // Configure the cell...
    // Configure the cell...
    Person  *person = nil;

    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        NSLog(@"Configuring cell to show search results");
        person = [self.searchResults objectAtIndex:indexPath.row];
    }
    else
    {
        NSLog(@"Configuring cell to show normal data");
        person = [self.fetchedResultsController objectAtIndexPath:indexPath];
    }








    NSString *fullname = [NSString stringWithFormat:@"%@ %@", person.firstname, person.surname];
    cell.textLabel.text = person.firstname;
    if ([person.inRole.color isEqual :@"Yellow"])
    {
        cell.imageView.image = [UIImage imageNamed:@"Yellow"];
    }
    if ([person.inRole.color isEqual :@"Black"])
    {
        cell.imageView.image = [UIImage imageNamed:@"Black"];
    }
    if ([person.inRole.color isEqual :@"Grey"])
    {
        cell.imageView.image = [UIImage imageNamed:@"Grey"];
    }
    if ([person.inRole.color isEqual :@"Red"])
    {
        cell.imageView.image = [UIImage imageNamed:@"Red"];
    }
    if ([person.inRole.color isEqual :@"Blue"])
    {
        cell.imageView.image = [UIImage imageNamed:@"Blue"];
    }
    if ([person.inRole.color isEqual :@"Dark Green"])
    {
        cell.imageView.image = [UIImage imageNamed:@"DarkGreen"];
    }
    if ([person.inRole.color isEqual :@"Light Green"])
    {
        cell.imageView.image = [UIImage imageNamed:@"LightGreen"];
    }
    if ([person.inRole.color isEqual :@"Light Blue"])
    {
        cell.imageView.image = [UIImage imageNamed:@"LightBlue"];
    }
    if ([person.inRole.color isEqual :@"Brown"])
    {
        cell.imageView.image = [UIImage imageNamed:@"Brown"];
    }
    if ([person.inRole.color isEqual :@"Dark Orange"])
    {
        cell.imageView.image = [UIImage imageNamed:@"DarkOrange"];



    }

    NSDate *fechasinformat = person.date;
    NSString *fecha0 = [NSString stringWithFormat:@"%@", fechasinformat];


   cell.detailTextLabel.text = fecha0;



    return cell;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        return [self.searchResults count];
    }
    else
    {
        return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
    }

}


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {




    if (editingStyle == UITableViewCellEditingStyleDelete) {

        [self.tableView beginUpdates]; // Avoid  NSInternalInconsistencyException

        // Delete the person object that was swiped
        Person *personToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
        NSLog(@"Deleting (%@)", personToDelete.firstname);
        [self.managedObjectContext deleteObject:personToDelete];
        [self.managedObjectContext save:nil];

        // Delete the (now empty) row on the table
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];




        [self performFetch];





        [self.tableView endUpdates];
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"Add Person Segue"])
    {
        NSLog(@"Setting PersonsTVC as a delegate of PersonDetailTVC");
        PersonDetailTVC *personDetailTVC = segue.destinationViewController;
        personDetailTVC.delegate = self;

        NSLog(@"Creating a new person and passing it to PersonDetailTVC");
        Person *newPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person"
                                                          inManagedObjectContext:self.managedObjectContext];

        personDetailTVC.person = newPerson;
    }
    else if ([segue.identifier isEqualToString:@"Person Detail Segue"])
    {
        NSLog(@"Setting PersonsTVC as a delegate of PersonDetailTVC");
        PersonDetailTVC *personDetailTVC = segue.destinationViewController;
        personDetailTVC.delegate = self;

        // Store selected Person in selectedPerson property
        if(sender == self.searchDisplayController.searchResultsTableView)
        {
            NSIndexPath *indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
            self.selectedPerson = [self.searchResults objectAtIndex:[indexPath row]];
        }
        else
        {
            NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
            self.selectedPerson = [self.fetchedResultsController objectAtIndexPath:indexPath];
        }

        NSLog(@"Passing selected person (%@) to PersonDetailTVC",    self.selectedPerson.firstname);
        personDetailTVC.person = self.selectedPerson;
    }
    else
    {
        NSLog(@"Unidentified Segue Attempted!");
    }
}

- (void)theSaveButtonOnThePersonDetailTVCWasTapped:(PersonDetailTVC *)controller
{
    // do something here like refreshing the table or whatever

    // close the delegated view
    [controller.navigationController popViewControllerAnimated:YES];    
}

#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) {
        Person* person = evaluatedObject;
        NSString* firstName = person.firstname;

        //searchText having length < 3 should not be considered
        if (!!searchText && [searchText length] < 3) {
            return YES;
        }

        if ([scope isEqualToString:@"All"] || [firstName isEqualToString:scope])  {
            return ([firstName 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;
}


@end

最佳答案

该错误清楚地表明您删除了 1 个部分,删除前有 1 个部分,删除后有 1 个部分。这就是问题。所以可能是你的

- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView

删除最后一个对象后返回不正确的节数。

删除最后一个对象后,您的[[self.fetchedResultsControllersections]count]不为0,或者numberOfSectionsInTableView:(UITableView *)tableView调用>self.searchDisplayController.searchResultsTableView 并且您不检查它。

编辑:要解决该问题,请添加以下代码:

- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    if(tableView==self.searchDisplayController.searchResultsTableView)
        NSLog("search table asking");
    else
        NSLog("main table asking");
    NSLog("fetched sections: %d", [[self.fetchedResultsController sections] count]);
    return [[self.fetchedResultsController sections] count];
}

并在崩溃发生时发布控制台输出。

关于ios - 删除部分的最后一行后,应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20293902/

相关文章:

android - 跨平台建议 Android/iOS/Windows

ios - 使用相同的捆绑标识符时更改 Appstore 上的应用名称

ios - swift UITableView 设置行宽

ios - Realm 未正确删除

iphone - NS小数乘法

iphone - iPhone 相机图像上的 3D 模型。透明背景?

ios - UITraitCollection - 快速到 objective-C

ios - 不要在 UITableView 中重复使用单元格

iphone - 我这里的副本有什么问题?

ios - 单例核心数据方法