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

OKAYだから、このコードを実行すると...

このタイプのエラーが発生します...

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 の最初の Rewrite ゲッター

- (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 に答える