0

我想从我的 tableviewcontroller 单元格中删除记录。

代码对我来说似乎很好,当我按下一行删除时出现异常......

这是我的 ViewController.h 文件的代码

#import <UIKit/UIKit.h>

@interface IMSCategoryViewController : UITableViewController
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property(nonatomic,retain)NSArray *arr;
@property (readonly, strong, nonatomic) NSMutableArray *categoryArray;
@end

而这个在实现文件中。

#import "IMSCategoryViewController.h"
#import "IMSAppDelegate.h"
#import "Category.h"

@interface IMSCategoryViewController ()
{
    NSManagedObjectContext *context;
}
@end

@implementation IMSCategoryViewController
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize categoryArray;
@synthesize arr;

- (void)viewDidLoad
{
    [super viewDidLoad];

    //    [self.tableView reloadData];

    IMSAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];

    context = [appDelegate managedObjectContext];

    NSEntityDescription *category = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:context];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    [request setEntity:category];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"is_active == 1"];

    [request setPredicate:predicate];

    [request setFetchBatchSize:25];


    [request setEntity:category];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

    NSArray *srotDesc = [[NSArray alloc]initWithObjects:sort, nil];

    [request setSortDescriptors:srotDesc];

    NSError *error;

    NSMutableArray *results = [[context executeFetchRequest:request error:&error] mutableCopy];

    if (results == nil) {

        //error handle here
    }

    [self setArr:results];

    NSLog(@"there is category array");

    [self.tableView reloadData];


    [self.arr count];

    }


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    return [self.arr count];
}

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

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

    Category *category = [self.arr objectAtIndex:indexPath.row];

    // Configure the cell...
    cell.textLabel.text = [category name];

    cell.detailTextLabel.text = [category descript];

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

以及我在哪里执行删除操作。

 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        NSManagedObject *recordtoDelete = [self.arr objectAtIndex:indexPath.row];


        [_managedObjectContext deleteObject:recordtoDelete];

        [self.tableView beginUpdates];

       // Category *deleteRecord = [self.arr objectAtIndex:indexPath.row];
       // [self.managedObjectContext deleteObject:deleteRecord];


        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade];

        [self.tableView endUpdates];


        NSError *error = nil;



        if (![_managedObjectContext save:&error]) {

            //handle error here
        }

    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}

好的所以当我运行这段代码时......

它给出了这种类型的错误......

Terminating app due to uncaught exception `NSInternalInconsistencyException`,reason: 
'Invalid update: invalid number of rows in section 0. 
The number of rows contained in an existing section after the update (17) must be 
equal to the number of rows contained in that section before the update (17), 
plus or minus the number of rows inserted or deleted from that section 
(0 inserted,1 deleted) and plus or minus the number of rows moved into or out of 
that section (0 moved in, 0 moved out).

'

4

1 回答 1

1

使用 NSFetchResultController 比使用数组更好,您可以使用 NSFetchResultControllerDelgate 轻松更新 tableView。在 UItableViewController 中只需要 2 个,如下所示:

@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;

NSFetchedResultController 的第一个重写 getter

- (NSFetchedResultsController *)fetchedResultsController

{
if (_fetchedResultsController != nil) {
    return _fetchedResultsController;
}

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"is_active == 1"];

[fetchRequest setPredicate:predicate];

[fetchRequest setFetchBatchSize:25];


// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = @[sortDescriptor];

[fetchRequest setSortDescriptors:sortDescriptors];

// 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:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

return _fetchedResultsController;
}    

重写数据源

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.fetchedResultsController sections] count];
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    Category *category = (Category *)[self.fetchedResultsController objectAtIndexPath:indexPath];

    // Configure the cell...
    cell.textLabel.text = [category name];

    cell.detailTextLabel.text = [category descript];

}

删除

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
        [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];

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


- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [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
{
    UITableView *tableView = self.tableView;

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

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

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];
}
于 2013-10-02T16:35:18.283 回答