2

2013 年 11 月 24 日:我做了更多调试,我发现 removeProject 工作正常。(我在删除前后打印了所有项目)只有当它返回 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 时,计数为 0 而不是(total - 1)。

=============

我现在被这个错误困住了一段时间。为了更好地理解 Core Data,我创建了这个测试项目,您可以在其中输入客户和他的项目。这些项目与客户有关。对于项目,我复制了 Clients 的 ViewController 并进行了一些小改动。我可以输入几个客户,然后删除它们。当我想删除相关项目时,问题就开始了。如果有一个客户只有一个项目,我可以删除它而不会出现任何错误。如果客户有两个或更多项目,我无法从该客户中删除任何项目。删除会给我这个错误:

2013-10-30 10:00:23.145 [6160:70b] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2903.2/UITableView.m:1330
2013-10-30 10:00:23.147 [6160:70b] *** 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 (0) must be equal to the number of rows contained in that section before the update (2), 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).'
*** First throw call stack:
(

 .....
     )
     libc++abi.dylib: terminating with uncaught exception of type NSException
     Program ended with exit code: 0 

在这个网站上阅读了很多答案之后,我的猜测是我需要在 numberOfRowsInSection 方法中更改我的代码,但我看不到那里要更改什么。

我的代码:

我创建了一个数据存储区:

数据存储.m

    #import "BITDataStore.h"
    #import "Client.h"
    #import "Project.h"

    @implementation DataStore


+ (BITDataStore *)sharedStore
{
    static BITDataStore *sharedStore = nil;
    if (!sharedStore) 
        sharedStore = [[super allocWithZone:nil]init];

        return sharedStore;
}    

-(void)removeClient:(Client *)client
{
    // remove from NSManagedObjectContext
    [context deleteObject:client];

    // remove from allClients array
    [allClients removeObjectIdenticalTo:client];
    NSLog(@"remove client");
}

-(void)removeProject:(Project *)project
{
    // remove from NSManagedObjectContext
    [context deleteObject:project];

    // remove from allProjects array
    [allProjects removeObjectIdenticalTo:project];

    // remove from relatedProjects array 
    [relatedProjects removeObjectIdenticalTo:project];
    NSLog(@"remove project %@", [project project]);

}


-(NSArray *)relatedProjects:(Client *)client;
{
    NSFetchRequest *request = [[NSFetchRequest alloc]init];

    NSEntityDescription *e = [[model entitiesByName] objectForKey:@"Project"];

    [request setEntity:e];

    // Check if client is related to Project
    [request setPredicate: [NSPredicate predicateWithFormat:@"clients == %@", client.objectID]];

    NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"project"
                                                         ascending:YES];
    [request setSortDescriptors:[NSArray arrayWithObject:sd]];

    NSError *error;
    NSArray *result = [context executeFetchRequest:request error:&error];

    if (!result) {
        [NSException raise:@"Fetch failed"
                    format:@"Reason: %@", [error localizedDescription]];
    }
    relatedProjects = [[NSMutableArray alloc] initWithArray:result];

    return relatedProjects;
}   
@end

项目数据视图控制器.m

@synthesize client, project;


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


#pragma mark - Table view data source

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [[[BITDataStore sharedStore]relatedProjects:client]count];        
}


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

    // Configure the cell...
    if (cell == nil){
        cell = [[UITableViewCell alloc]
                initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }

   Project *p = [[[BITDataStore sharedStore]relatedProjects:client]
                                              objectAtIndex:[indexPath row]];

    [[cell textLabel] setText:[p project]];

    return cell;
}

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        BITDataStore *ds = [BITDataStore sharedStore];
        NSArray *selectedProjects = [ds relatedProjects:client];

        Project *pr = [selectedProjects objectAtIndex:[indexPath row]];
        NSLog(@"Deleting project %@", [pr project]);
       [ds removeProject:pr];

        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        // Finally, reload data in view
        [[self tableView] reloadData];
        NSLog(@"Reload data"); 
    }   
    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
    }   
}

@end

希望这是足够的信息,如果没有,请告诉我。

4

2 回答 2

2

将我的删除规则从级联更改为无效并且它有效。

于 2013-12-10T15:50:06.183 回答
0

尽管需要阅读更多代码才能确定,但​​从您的描述来看,问题似乎在于删除元素时表格视图的更新不正确。

为了更好地理解 Core Data,我创建了这个测试项目

我的建议是从标准的 Apple 模板之一开始。特别是,它们展示了如何使用NSFetchedResultsController来避免此类问题。

您还可以查看博文Core Data Tutorial for iOS: How To Use NSFetchedResultsController

于 2013-11-15T20:36:25.987 回答