通过NSNotification从UICollectionView中删除单元格

时间:2012-10-15 10:58:02

标签: ios uicollectionview uicollectionviewcell

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

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

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

但是,我尝试通过UIMenuController子类中的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:call

上崩溃了
-[UICollectionViewUpdateItem action]: unrecognized selector sent to instance 0xee7eb10

我已经检查了所有明显的东西 - 比如来自NSNotification的对象和从indexPathForCell:call创建的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)

更新后的索引路径可能很重......

有什么想法吗?

3 个答案:

答案 0 :(得分:25)

我找到了一个粗略但有效的解决方法,它甚至会检查行动是否已在未来版本中实施(优于类别)

// 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的检查 编辑2:我们在许多商业项目(http://pspdfkit.com)中发布了它,并且效果很好。

答案 1 :(得分:0)

您可以传递通知的NSIndexPath字典中所选单元格的userInfo。您可以在创建自定义单元格的tag时将其设置为。

答案 2 :(得分:0)

我有同样的问题。在我在UICollectionView中选择放置在collectionViewCell内的文本后,当我尝试将单元格插入UITextField时,我的应用会崩溃。我的解决方法是在插入发生之前辞职第一响应者。由于我使用NSFetchedResultsController来处理更新,因此我将其放在controllerWillChangeContent:的开头

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

我找到了findAndResignFirstResponder from this SO answer