2013-10-30 40 views
2

11-24-2013:我做了一些更多的調試,我發現的是removeProject工作正常。 (我已經打印所有項目之前和之後刪除)只有當它回來 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)部分計數爲0而不是(總計 - 1)。刪除行:錯誤'更新無效:0節中的行數無效'

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

我被困在這個錯誤有一段時間了。爲了更好地理解Core Data,我創建了這個測試項目,您可以在其中輸入客戶和他的項目。這些項目與客戶有關。 對於我已經複製了客戶端的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方法我的代碼,但我看不出有什麼改變那裏。

我的代碼:

我創建了一個數據存儲:

DataStore.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 

ProjectDataViewController.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 

希望這是足夠的信息,如果不討好讓我知道。

+1

代碼轉儲過多。請減少。 – Mundi

+0

謝謝,我已經減少了代碼。 – Eloy

+0

您的deleteObject可能是問題。例如,如果你從一個NSMutableArray中刪除,delete(removeObjectAtIndex依次)只會插入nil。它不會刪除整個對象。看看它。其他一切似乎都很好。 –

回答

2

將我的刪除規則從級聯更改爲無效,並且工作正常。

0

儘管您需要閱讀更多的代碼才能確定,但​​從您的描述中可以看出,當您刪除元素時,問題出在表格視圖的更新不正確。

To understand Core Data better, I have created this test project

我的建議是從一個標準的Apple模板開始。特別是,他們展示如何使用NSFetchedResultsController來避免這類問題。

你也可以看看博文Core Data Tutorial for iOS: How To Use NSFetchedResultsController

相關問題