サーバーから製品のリストを取得するアプリを作成しています。次に、それらを Core Data データベースに保存し、GMGridViewを使用して表示します。データソースは NSFetchedResultsController です。サーバーで製品の詳細を変更するときに、iOS アプリを同期して必要な変更を加えたいので、NSFetchedResultsControllerDelegate メソッドを実装します。gridView を適切に更新するにはどうすればよいですか?
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[_currentData insertObject:anObject atIndex:newIndexPath.row];
[_currentData removeObjectAtIndex:indexPath.row];
[_gmGridView insertObjectAtIndex:newIndexPath.row animated:YES];
[_gmGridView removeObjectAtIndex:indexPath.row animated:YES];
[_gmGridView reloadObjectAtIndex:newIndexPath.row animated:YES];
[_gmGridView reloadObjectAtIndex:indexPath.row animated:YES];
[_gmGridView reloadData];
//[self updatePageControl];
break;
case NSFetchedResultsChangeDelete:
[_currentData removeObjectAtIndex:indexPath.row];
[_gmGridView removeObjectAtIndex:indexPath.row animated:YES];
//[self updatePageControl];
[_gmGridView reloadInputViews];
[_gmGridView reloadData];
break;
case NSFetchedResultsChangeUpdate:
[_gmGridView reloadObjectAtIndex:indexPath.row animated:YES];
////////might be irrelevant, but just trying it out
[_currentData insertObject:anObject atIndex:newIndexPath.row];
[_currentData removeObjectAtIndex:indexPath.row];
[_gmGridView insertObjectAtIndex:newIndexPath.row animated:YES];
[_gmGridView removeObjectAtIndex:indexPath.row animated:YES];
[_gmGridView reloadObjectAtIndex:newIndexPath.row animated:YES];
[_gmGridView reloadObjectAtIndex:indexPath.row animated:YES];
////////
[_gmGridView reloadInputViews];
[_gmGridView reloadData];
break;
case NSFetchedResultsChangeMove:
[_currentData removeObjectAtIndex:indexPath.row];
[_currentData insertObject:anObject atIndex:newIndexPath.row];
[_gmGridView removeObjectAtIndex:indexPath.row animated:YES];
[_gmGridView insertObjectAtIndex:newIndexPath.row animated:YES];
[_gmGridView reloadInputViews];
[_gmGridView reloadData];
break;
}
}
いくつかの詳細:
_currentData = [[self.fetchedResultsController fetchedObjects]mutableCopy];
//I did this because previously I wasn't using a fetchedResultsController but a NSMutableArray instead. I know that it's inefficient (because I have 2 models) but this is the simplest implementation I want to do now.
同じローカル URL から割り当てられた同じ UIManagedDocument を変更して、別のクラスで CoreData を変更します。
ただし、次の 2 つの重要な問題があります。
- データベース内のアイテムは更新されますが (製品名や価格の変更など)、変更が UI に反映されません。つまり、GMGridViewCell を正しく再読み込みできません。(上記のリロードに関連するコードに注意してください)
- ほとんどの場合、サーバーで更新した製品はデータベースで複製されますが、このようなエラーを防ぐメカニズムはあります。(商品を作成する前に、まず一意の識別子を使用して既存の商品を検索します。既存の商品があれば、その詳細を変更するだけです)。コードは次のとおりです。
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Product"];
request.predicate = [NSPredicate predicateWithFormat:@"product_id = %@", [imonggoInfo objectForKey:PRODUCT_ID]];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
request.sortDescriptors = [NSArray
arrayWithObject:sortDescriptor]; NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
if (!matches | ([matches count] > 1)){
//handle error
}else if ([matches count] == 0){
//make a new product
}else{
//return existing
item = [matches lastObject];
}