我第一次使用UICollectionView,而且遇到了一些困难。特别是更新和删除单元格(将集中在这里删除,希望是原因),来自NSFetchResultController
的数据。我在界面构建器中创建了一个自定义单元格作为故事板的一部分,如下所示:
我有一个自定义UICollectionViewCell
子类,其中包含以下属性:
@property (strong, nonatomic) IBOutlet UIButton *deleteButton;
@property (strong, nonatomic) IBOutlet UITextField *textField;
@property (strong, nonatomic) IBOutlet UIView *containerView;
@property (strong, nonatomic) IBOutlet UIView *textFieldContainer;
在IB中,我将单元类设置为自定义类,将元素连接到自定义类的属性,并将标识符设置为Cell
。
在我的Collection View视图控制器中,我设置了集合视图和fetchResultController以及类似的相关方法:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NoteCollectionViewCell* cell = (NoteCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(NoteCollectionViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
cell.deleteButton.tag = indexPath.row;
[cell.deleteButton addTarget:self action:@selector(deleteNote:) forControlEvents:UIControlEventTouchUpInside];
[...]
// I'm having some weird problem with this, se description below.
Note *note = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textField.tag = indexPath.row;
cell.textField.delegate = self;
cell.textField.text = note.name;
[...]
#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController
{
[Default FRC method]
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UICollectionView *collectionView = self.collectionView;
switch(type) {
case NSFetchedResultsChangeInsert:
[collectionView insertItemsAtIndexPaths:@[newIndexPath]];
break;
case NSFetchedResultsChangeDelete:
[collectionView deleteItemsAtIndexPaths:@[indexPath]];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:(NoteCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath] atIndexPath:indexPath];
break;
}
}
我的删除操作如下所示:
- (void)deleteNote:(UIButton *)sender
{
Note *note = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForItem:sender.tag inSection:0]];
[[AppDelegate sharedAppDelegate].managedObjectContext deleteObject:note];
[[AppDelegate sharedAppDelegate] saveContext];
}
我的更新操作(UITextField
委托方法)如下所示:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
Note *note = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForItem:textField.tag inSection:0]];
note.name = textField.text;
[[AppDelegate sharedAppDelegate] saveContext];
}
问题如下:
关于如何解决这些问题的任何想法都会很棒!
更新
如下面的评论,我的deleteNote
操作中的此日志始终为indexPath行返回0。不知道那可能是原因。
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:sender.tag inSection:0];
NSLog(@"indexPath: %@. Row: %d", indexPath, indexPath.row);
答案 0 :(得分:4)
您无法将获取的结果控制器链接到集合视图,其方式与表视图完全相同。获取的结果控制器专门用于在核心数据和表视图之间进行调解,因此委托方法与表视图的工作方式相关。
主要区别在于表视图有一个beginUpdates
/ endUpdates
方法对,您可以将所有更新包装在其中。集合视图没有这个,您必须构建自己完成所有必需的更新调用,然后当获取的结果控制器完成更新时,在performBatchUpdates:completion:
调用内全部执行它们。
此on GitHub有一个示例实现。
答案 1 :(得分:1)
我不知道这是否能解释您的问题,但您致电
[cell.deleteButton addTarget:self action:@selector(deleteNote:) forControlEvents:UIControlEventTouchUpInside];
configureCell:atIndexPath:
中的每次 ,以便将多个操作附加到。{1}}
如果单元格被修改或重用,则为按钮。然后调用deleteNote:
一次触摸事件不止一次。
作为一种解决方法,您可以检查cell.deleteButton.tag
以查看某个操作是否已附加到该按钮,或更好:
NoteCollectionViewCell
课程中添加操作
创建单元格时,该类中的本地操作