我有一个带有UICollectionView的应用程序,该视图显示自定义UICollectionViewCells。当其中一个单元格注册一个tap时,它会以模型视图控制器的形式打开一个详细视图。集合视图中填充了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);
}
当我创建一个新的Produkt对象(NSManagedObject)时,保存它并重新加载UICollectionView一切正常。这是创建新的Produkt-Object的代码:
-(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.在我取消视图控制器后,集合视图再次更改顺序。当我重新启动应用程序时,我对对象所做的更改不会保存。
在主视图控制器中,我创建了一个NSMangedObjectContext,我将其传递给其他控制器,因此我总是保持在相同的上下文中。
AppDelegate *appDelegate =
[[UIApplication sharedApplication] delegate];
context =
[appDelegate managedObjectContext];
感谢您的帮助。
答案 0 :(得分:2)
没有排序描述符,获取请求返回的对象的顺序是 未定义。甚至不能保证两个相同的提取请求返回 对象的顺序相同。
由于所有集合视图数据源方法都执行新的获取请求(其中 非常无效!)没有什么可以说是关于哪个对象
Produkt* produkt = [[self refreshTableData]objectAtIndex:indexPath.row];
<{1}}中的实际上会返回。
因此,一种可能的解决方案是将对象提取到cellForItemAtIndexPath
并使用
此数组作为集合视图数据源。如果已添加或修改对象,
执行新的获取请求并重新加载集合视图。
另一种可能的解决方案是使用NSArray
(FRC)。
FRC自动跟踪对托管对象上下文的更改并进行调用
如果插入,删除或修改对象,则委托函数。如果你选择那个
您应该注意,使用带有集合视图的FRC会有点棘手
而关于自动动画更新的表格视图。但
这篇文章http://ashfurrow.com/blog/uicollectionview-example可能会有所帮助。