通过NSNotification从UICollectionView中删除单元格

我有一个简单的基于UICollectionView的应用程序 – 一个UICollectionView和一个基于NSMutableArray的数据模型。

我可以通过didSelectItemAtIndexPath:delegate方法删除没有问题的单元格:

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ [self.data removeObjectAtIndex:[indexPath row]]; [self.collectionView deleteItemsAtIndexPaths:@[indexPath]]; } 

不过,我想通过UICollectionViewCell子类中的UICollectionViewCell通过UILongPressGestureRecognizer ,这一切都工作正常,我成功地触发NSNotification

 -(void)delete:(id)sender{ NSLog(@"Sending deleteme message"); [[NSNotificationCenter defaultCenter] postNotificationName:@"DeleteMe!" object:self userInfo:nil]; } 

我在我的ViewController中捕获它,并调用以下方法:

 -(void)deleteCell:(NSNotification*)note{ MyCollectionViewCell *cell = [note object]; NSIndexPath *path = nil; if((path = [self.collectionView indexPathForCell:cell]) != nil){ [self.data removeObjectAtIndex:[path row]]; [self.collectionView deleteItemsAtIndexPaths:@[path]]; } } 

它在deleteItemsAtIndexPaths:调用中崩溃

 -[UICollectionViewUpdateItem action]: unrecognized selector sent to instance 0xee7eb10 

我已经检查了一切显而易见 – 如从NSNotification的对象和从indexPathForCell:调用创build的indexPath,这一切似乎完全正常。 看起来好像我调用deleteItemsAtIndexPath:在两个地方都有相同的信息,但由于某种原因,它通过通知路由时失败。

这是在错误中给出的地址的信息:

 (lldb) po 0xee7eb10 (int) $1 = 250080016 <UICollectionViewUpdateItem: 0xee7eb10> index path before update (<NSIndexPath 0x9283a20> 2 indexes [0, 0]) index path after update ((null)) action (delete) 

也许更新后的索引path为空是有意义的…

有任何想法吗?

我发现了一个粗糙而又有效的解决方法,它甚至会检查在未来版本中是否已经实施了行动(比类别更好)

 // Fixes the missing action method when the keyboard is visible #import <objc/runtime.h> #import <objc/message.h> __attribute__((constructor)) static void PSPDFFixCollectionViewUpdateItemWhenKeyboardIsDisplayed(void) { @autoreleasepool { if ([UICollectionViewUpdateItem class] == nil) return; // pre-iOS6. if (![UICollectionViewUpdateItem instancesRespondToSelector:@selector(action)]) { IMP updateIMP = imp_implementationWithBlock(^(id _self) {}); Method method = class_getInstanceMethod([UICollectionViewUpdateItem class], @selector(action)); const char *encoding = method_getTypeEncoding(method); if (!class_addMethod([UICollectionViewUpdateItem class], @selector(action), updateIMP, encoding)) { NSLog(@"Failed to add action: workaround"); } } } } 

编辑:添加检查iOS5。
Edit2:我们在很多商业项目( http://pspdfkit.com )中都有这个function,效果很好。

您可以在您的通知的userInfo字典中传入选定单元格的NSIndexPath 。 您可以在自定义单元格的tag中设置它。

我遇到过同样的问题。 当我在放置在一个collectionViewCell中的UITextFieldselect了文本后,我的应用程序会崩溃,当我试图插入一个单元格到我的UICollectionView 。 我的修复是在插入发生之前辞去第一个响应者。 由于我使用NSFetchedResultsController来处理更新,我把这个在controllerWillChangeContent:的开头controllerWillChangeContent:

 - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [[UIApplication sharedApplication].keyWindow findAndResignFirstResponder]; ... } 

我从这个答案find了findAndResignFirstResponder