2

2013 年 11 月 24 日: さらにデバッグを行ったところ、removeProject が正常に動作していることがわかりました。(削除前後のすべてのプロジェクトを印刷しました) -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section に戻った場合のみ、カウントは (total - 1) ではなく 0 になります。

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

しばらくの間、このエラーで立ち往生しています。Core Data をよりよく理解するために、クライアントとそのプロジェクトを入力できるこのテスト プロジェクトを作成しました。プロジェクトはクライアントに関連しています。プロジェクトでは、Clients の ViewController をコピーし、いくつかの小さな変更を加えました。複数のクライアントを入力してから削除できます。関連するプロジェクトを削除したいときに問題が発生します。プロジェクトが 1 つしかないクライアントがあれば、エラーなく削除できます。クライアントに 2 つ以上のプロジェクトがある場合、このクライアントからプロジェクトを削除できません。削除すると、次のエラーが表示されます。

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

これで十分な情報だといいのですが、そうでない場合はお知らせください。

4

2 に答える 2

2

削除ルールをカスケードから無効化に変更したところ、機能しました。

于 2013-12-10T15:50:06.183 に答える
0

確かにコードをもっと読む必要がありますが、説明から、要素を削除するときにテーブルビューが正しく更新されていないように見えます。

Core Data をよりよく理解するために、このテスト プロジェクトを作成しました。

私の提案は、標準的な Apple のテンプレートの 1 つから始めることです。特に、NSFetchedResultsControllerこのクラスの問題を回避するための使用方法を示します。

また、ブログ記事iOS の Core Data Tutorial: How To Use NSFetchedResultsControllerも参照してください。

于 2013-11-15T20:36:25.987 に答える