私はコアデータに不慣れですが、それでも根本的な問題を理解しています。このエラーによって何時間も悩まされ、解決策を見つけることができません。どんな助けでも大歓迎です。
問題はこのようなものです
サーバーからデータをフェッチし、UIを更新する2つのビューがあります。このようにフローを設定しました
view1->サーバーからHTTP要求を送信-コールバックを受信-> Coredataにデータを保存->コアデータから読み取り、UIに表示(ViewControllerでコールバックとCoredataの保存/読み取りが発生)
view2->サーバーからHTTPリクエストを送信-コールバックを受信->データをCoredataに保存->コアデータから読み取り、UIに表示(ViewControllerでコールバックとCoredataの保存/読み取りが発生)
これは自動更新画面であるため、ビュー2は3秒ごとにこのプロセスを繰り返します。
問題は、ビュー1と2を非常に高速に切り替えようとすると、上記のエラーでアプリがクラッシュすることです。各ビューで数秒待つ(サーバーからデータがフェッチされるのを待つ)と、問題なく動作します。私は何か間違ったことをしていますか、何を変更する必要がありますか?
- (void) refreshData {
[super refreshData];
[[UserDataFactory sharedSingleton] refreshLoggedInUserDataAndRespondTo:self user:self.user];
}
- (BOOL) refreshDataCallback:(QExtendedHTTPOperation*)responseOperation {
[self saveToCoreData: responseOperation.responseArray];
NSMutableArray *tmp = [[NSMutableArray alloc] initWithArray:[self readFromCoreData]];
[self setData: tmp];
[tmp release];
[self.tableView reloadData];
return YES;
}
- (void) saveToCoreData:(NSArray *) responseArray{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSError *error;
NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
for (NSManagedObject *managedObject in items) {
[self.managedObjectContext deleteObject:managedObject];
}
for (int i=0; i<[responseArray count]; i++) {
CoreView1 *coreView1_ = [NSEntityDescription insertNewObjectForEntityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
coreView_.id = [[responseArray objectAtIndex:i] id];
[self.managedObjectContext insertObject:coreView1_];
}
[self saveContext:self.managedObjectContext];
}
- (NSArray *) readFromCoreData{
NSEntityDescription *entity = [NSEntityDescription entityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSError *error;
NSMutableArray *fetchedObjects = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
[fetchRequest release];
return [fetchedObjects autorelease];
}
これは私が使用しているサンプルコードです。View2でも同じコールバックがあり、同じフローに従います。
編集1これについて前に説明するのを忘れていたため、saveToCoreDataメソッドで常にエラーが発生しました。また、もう1つ注意すべき点は、オブジェクトを削除するコードを削除すると、すべて正常に機能することです(更新したデータを保存する前に、テーブルから既存のデータをすべて削除する必要があります)。何が起こっているのかわからない。
削除コードを削除すると機能する理由は、メモリ内のデータに関連付けられた管理オブジェクトインスタンスがまだ残っている他のビューを更新せずに永続ストアのデータを削除するためです。 Core Dataはオブジェクトを扱いますが、各オブジェクトはその背後にあるデータベースに行を持っている必要があります。その行を削除すると、Core Dataは怒ります。
したがって、この問題を修正し、データを削除するには、ビューにNSManagedObjectContextWillSaveNotification
および/またはNSManagedObjectContextDidSaveNotification
通知をリッスンさせ、ビュー内の最新バージョンのデータでビューを更新する必要がありますあなたの店。この時点で、ビューが保持しているCore Dataオブジェクトを破棄し、ストアから再ロードする必要があります。
私は自分のコードでこのエラーを解決しました。キャッシュが何らかの方法で破損しているようです。私はクリストファー・ピックスレイとキール・ギラードのキャッシュの削除または名前変更の提案を使用しましたが、できればクラッシュは解決しました。 範囲を超えるNSFetchedResultsControllerインデックス
情報については、昨日、同じエラーが発生しました。アプリのライブバージョンをチェックインしましたが、まだそこにありました。うわぁ。
クラッシュが発生するまで、コアデータスタックに情報を追加するすべての順列を実行しました。
次に、SqliteManagerを使用して、シミュレーターライブラリーのアプリからsqliteファイルを確認しました。 1つのテーブルでデータエラーが見つかりました。これは、アプリが初めて実行されたときに使用されたスターターデータベースがあるために発生していました。エラーは、スターターデータベースにありました。
アプリを再度実行し、各テーブルの各フィールドをテストしました。さらにいくつかの発生が見つかりました。私はこの質問を読んだことを覚えており、多分誰かが私の間違いから恩恵を受けることができると思いました。