UICollectionView を持つアプリを持っています。ビューにはカスタム UICollectionViewCells が表示されます。これらのセルの 1 つがタップを登録すると、モデル ビュー コントローラーの形式で詳細ビューが開きます。コレクション ビューには Core Data からのデータが表示され、次のようになります。
#pragma mark - Get Items From CoreData
-(NSArray*)refreshTableData
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Produkt"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError* error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
/*for (Produkt *produkt in fetchedObjects)
{
NSLog(@"Name: %@", produkt.name);
}*/
return fetchedObjects;
}
#pragma mark - UICollectionView Datasource
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection: (NSInteger)section {
return [[self refreshTableData] count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ItemCell" forIndexPath:indexPath];
Produkt* produkt = [[self refreshTableData]objectAtIndex:indexPath.row];
[cell.collectionLabel setText:produkt.name];
[cell.collectionImage setImage:[[UIImage alloc]initWithData:produkt.image]];
[cell.layer setCornerRadius:10];
[cell.layer setMasksToBounds:YES];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = cell.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], (id)[[UIColor whiteColor] CGColor], nil];
[cell.layer insertSublayer:gradient atIndex:0];
return cell;
}
#pragma mark UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
Produkt* produkt = [[self refreshTableData]objectAtIndex:indexPath.row];
produktView = [[ProduktViewController alloc]
initWithNibName:@"ProduktViewController"
bundle:nil];
produktView.modalPresentationStyle = UIModalPresentationFormSheet;
produktView.delegate = self;
produktView.produkt = produkt;
[self presentViewController:produktView animated:YES completion:nil];
}
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(50, 20, 50, 20);
}
新しい製品オブジェクト (NSManagedObject) を作成したら、それを保存して UICollectionView をリロードすると、すべて正常に動作します。これは、新しい製品オブジェクトを作成するためのコードです。
-(void)selectedItem:(NSString *)selectedItem
{
//Dismiss the popover if it's showing.
if (itemPickerPopover) {
[itemPickerPopover dismissPopoverAnimated:YES];
itemPickerPopover = nil;
}
if([selectedItem isEqualToString:@"Produkt"])
{
NSLog(@"SELECTED ITEM:%@",selectedItem);
produktView = [[ProduktViewController alloc]
initWithNibName:@"ProduktViewController"
bundle:nil];
Produkt* newProdukt = [NSEntityDescription
insertNewObjectForEntityForName:@"Produkt"
inManagedObjectContext:context];
produktView.modalPresentationStyle = UIModalPresentationFormSheet;
produktView.delegate = self;
produktView.context = context;
produktView.produkt = newProdukt;
[self presentViewController:produktView animated:YES completion:nil];
}
}
セルを選択すると詳細ビューがポップアップし、詳細ビューでデータを編集し、その後、この関数 (詳細ビュー クラスに含まれる) を使用して保存します。
-(void)saveChanges
{
NSLog(@"SAVE SAVE SAVE SAVE SAVE SAVE SAVE SAVE SAVE SAVE SAVE ");
produkt.name = name.text;
produkt.artikelNr = artikelNr.text;
produkt.gekauftBei = bestelltBei.text;
produkt.gebrauchsAnweisung = gebrauchsAnleitung.text;
NSData *savedImageData = UIImagePNGRepresentation(image.image);
produkt.image = savedImageData;
NSError *error;
[context save:&error];
}
詳細コントローラーがこのデリゲート関数を閉じると、次のように呼び出されます。
#pragma mark ProduktView delegate
-(void)didDismissPresentedViewController
{
NSLog(@"DISMISS CONTROLLER");
[produktView dismissViewControllerAnimated:YES completion:nil];
[collectionView reloadData];
}
ここで問題が発生します。変更したオブジェクトを保存してテーブル ビューをリロードすると、表示されたセルが間違ったエンティティに関連付けられます。たとえば、コレクション ビューにはオブジェクト 1 、 2 、 3 、 4 が表示されますが、たとえばオブジェクト 3 をクリックすると、詳細ビューにオブジェクト 1 が表示されます。View Controller を閉じた後、コレクション ビューの順序が再び変更されます。アプリを再起動すると、オブジェクトに加えた変更が保存されません。
メイン ビュー コントローラーで、他のコントローラーに渡す 1 つの NSMangedObjectContext を作成したので、常に同じコンテキストにとどまります。
AppDelegate *appDelegate =
[[UIApplication sharedApplication] delegate];
context =
[appDelegate managedObjectContext];
ご協力いただきありがとうございます。