レッスンをJSONとしてダウンロードし、解析してコアデータに入れるコードがいくつかあります。その後、UITableViewに表示されます。現在、ユーザーが多くのレッスンを受けていると、接続がタイムアウトすることがあります。そこで、(SBJsonを使用して)入ってくるレッスンを解析し、一度に1つずつテーブルビューに追加しようとしています。
2つのコードは基本的に同じですが、新しいコードを使用すると、tableViewが起動するとクラッシュし、エラーが発生します。
"Terminating app due to uncaught exception
'NSObjectInaccessibleException', reason: 'The NSManagedObject with ID:0x5ad0570 <x-coredata://A21AC71F-175B-423D-BF7D-C67BEE094460/Lessons/p18> has been invalidated.'"
このエラーの原因となっている可能性のあるこれら2つのコードリストの違いを知りたいのですが。元のコードはループ内で各コアデータオブジェクトを作成しますが、新しいコードはダウンロード時に各コアデータオブジェクトを作成します。listViewArrayは、UITableViewにデータを入力するために使用される配列です。
私はSBJsonStreamParserとSBJsonStreamParserAdapterを使用して、入ってくるJsonを解析しています。
私は、新しいオブジェクトが受信されるたびに(受信したオブジェクトの完全なループを毎回実行する)、基本的に以下の元のコードを呼び出す、動作する実装(図示せず)を持っています。エラーの原因を知りたいのですが、何かが機能するだけではありません。
これは、connectionDidFinishLoadingで呼び出される元の非ストリーミングコードです。
NSMutableArray *tempListArray = [[NSMutableArray alloc] initWithArray:jsonStreamedData];
if (listViewArray)
[listViewArray release];
listViewArray = [[NSMutableArray alloc] init];
if(![tempListArray count]){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Message" message:@"No active lessons " delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alertView show];
[alertView release];
}
else {
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSError *error = nil;
[appDelegate.managedObjectContext reset];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
for (int i = 0; i < [tempListArray count]; i++) {
NSFetchRequest *checkRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *lessonEntity = [NSEntityDescription entityForName:@"Lessons" inManagedObjectContext:managedObjectContext];
[checkRequest setEntity:lessonEntity];
NSPredicate *langPredicate = [NSPredicate predicateWithFormat:@"(language = %@)", appDelegate.currentLanguage];
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"(username = %@)", appDelegate.userName];
NSPredicate *idPredicate = [NSPredicate predicateWithFormat:@"(content_Id = %@)", [[tempListArray objectAtIndex:i] valueForKey:@"id"]];
[checkRequest setPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:langPredicate, userPredicate, idPredicate, nil]]];
NSArray *checkResults = [managedObjectContext executeFetchRequest:checkRequest error:&error];
[checkRequest release];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
if ([checkResults count]) {
Lessons *lessonObj = [checkResults objectAtIndex:0];
lessonObj.cards_count = [[tempListArray objectAtIndex:i] valueForKey:@"cards_count"];
lessonObj.mTitle = [[tempListArray objectAtIndex:i] valueForKey:@"title"];
lessonObj.sound_Url = [[tempListArray objectAtIndex:i] valueForKey:@"audio_url"];
lessonObj.mId = [NSNumber numberWithInt:i];
[tempDict setValue:lessonObj forKey:@"lesson"];
[tempDict setValue: [[tempListArray objectAtIndex:i] objectForKey:@"image_url"] forKey:@"image_url"];
[listViewArray addObject:tempDict];
}
else {
Lessons *newLesson = (Lessons *)[NSEntityDescription insertNewObjectForEntityForName:@"Lessons" inManagedObjectContext:appDelegate.managedObjectContext];
newLesson.cards_count = [[tempListArray objectAtIndex:i] valueForKey:@"cards_count"];
newLesson.mTitle = [[tempListArray objectAtIndex:i] valueForKey:@"title"];
newLesson.sound_Url = [[tempListArray objectAtIndex:i] valueForKey:@"audio_url"];
newLesson.content_Id = [[tempListArray objectAtIndex:i] valueForKey:@"id"];
newLesson.username = appDelegate.userName;
newLesson.language = appDelegate.currentLanguage;
newLesson.mId = [NSNumber numberWithInt:i];
[tempDict setValue:newLesson forKey:@"lesson"];
[tempDict setValue: [[tempListArray objectAtIndex:i] objectForKey:@"image_url"] forKey:@"image_url"];
[listViewArray addObject:tempDict];
}
[tempDict release];
tempDict = nil;
}
if (![appDelegate.managedObjectContext save:&error]) {
NSLog(@"Core Data Error - %@", [error localizedDescription]);
}
// NSMutableArray *tempArray = [NSMutableArray arrayWithArray:listViewArray];
// [listViewArray removeAllObjects];
// [listViewArray addObjectsFromArray:[[tempArray reverseObjectEnumerator] allObjects]];
// tempArray = nil;
}
[tempListArray release];
}
[mListsTableView reloadData];
そして、これがクラッシュするコードで、parser:foundObjectで呼び出されます。ループコードは削除されました。これは、新しいJsonオブジェクトがダウンロードされるたびに呼び出されるためです。
[jsonStreamedData addObject:dict];
if (!listViewArray)
listViewArray = [[NSMutableArray alloc] init];
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSError *error = nil;
[appDelegate.managedObjectContext reset];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *checkRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *lessonEntity = [NSEntityDescription entityForName:@"Lessons" inManagedObjectContext:managedObjectContext];
[checkRequest setEntity:lessonEntity];
NSPredicate *langPredicate = [NSPredicate predicateWithFormat:@"(language = %@)", appDelegate.currentLanguage];
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"(username = %@)", appDelegate.userName];
NSPredicate *idPredicate = [NSPredicate predicateWithFormat:@"(content_Id = %@)", [dict valueForKey:@"id"]];
[checkRequest setPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:langPredicate, userPredicate, idPredicate, nil]]];
NSArray *checkResults = [managedObjectContext executeFetchRequest:checkRequest error:&error];
[checkRequest release];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
if ([checkResults count]) {
Lessons *lessonObj = [checkResults objectAtIndex:0];
lessonObj.cards_count = [dict valueForKey:@"cards_count"];
lessonObj.mTitle = [dict valueForKey:@"title"];
lessonObj.sound_Url = [dict valueForKey:@"audio_url"];
lessonObj.mId = [NSNumber numberWithInt:jsonStreamedData.count - 1]; // This should be equivalent to i from the loop in the first code
[tempDict setValue:lessonObj forKey:@"lesson"];
[tempDict setValue: [dict objectForKey:@"image_url"] forKey:@"image_url"];
[listViewArray addObject:tempDict];
}
else {
Lessons *newLesson = (Lessons *)[NSEntityDescription insertNewObjectForEntityForName:@"Lessons" inManagedObjectContext:appDelegate.managedObjectContext];
newLesson.cards_count = [dict valueForKey:@"cards_count"];
newLesson.mTitle = [dict valueForKey:@"title"];
newLesson.sound_Url = [dict valueForKey:@"audio_url"];
newLesson.content_Id = [dict valueForKey:@"id"];
newLesson.username = appDelegate.userName;
newLesson.language = appDelegate.currentLanguage;
newLesson.mId = [NSNumber numberWithInt:jsonStreamedData.count - 1];
[tempDict setValue:newLesson forKey:@"lesson"];
[tempDict setValue: [dict objectForKey:@"image_url"] forKey:@"image_url"];
[listViewArray addObject:tempDict];
}
[tempDict release];
tempDict = nil;
if (![appDelegate.managedObjectContext save:&error]) {
ALog(@"Core Data Error - %@", [error localizedDescription]);
}
// NSMutableArray *tempArray = [NSMutableArray arrayWithArray:listViewArray];
// [listViewArray removeAllObjects];
// [listViewArray addObjectsFromArray:[[tempArray reverseObjectEnumerator] allObjects]];
// tempArray = nil;
//[self getListsLocally];
[mListsTableView reloadData];
最後に、tableView:cellForRowAtIndexPathの2番目のリストを使用するとクラッシュする実際の部分は次のとおりです。ちなみに、行==0ではなく行==1のときにクラッシュします。何らかの理由で行0は問題ありません...決してもちろん、他の行をロードする機会があります。
titleLabel.text = [[[listViewArray objectAtIndex:indexPath.row] valueForKey:@"lesson"] valueForKey:@"mTitle"]; // CRASH!
labelCards.text = [NSString stringWithFormat:@"%@ Cards", [[[listViewArray objectAtIndex:indexPath.row] valueForKey:@"lesson"] valueForKey:@"cards_count"]];
if([[listViewArray objectAtIndex:indexPath.row] objectForKey:@"userImageObj"] == nil){
mImageView.backgroundColor = [UIColor grayColor];
if ([[listViewArray objectAtIndex:indexPath.row] objectForKey:@"isThreadLaunched"] == nil) {
[NSThread detachNewThreadSelector:@selector(loadImagesInBackground:) toTarget:self withObject:[NSNumber numberWithInt:indexPath.row]];
[[listViewArray objectAtIndex:indexPath.row] setObject:@"Yes" forKey:@"isThreadLaunched"];
}
}else {
mImageView.image = [[listViewArray objectAtIndex:indexPath.row] objectForKey:@"userImageObj"];
}