Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleting cells from UICollectionView via NSNotification

I have a simple UICollectionView based app - one UICollectionView and a NSMutableArray based data model for simplicity.

I can delete cells with no problem via the didSelectItemAtIndexPath: delegate method:

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

However, I'm trying to add a delete option via a UIMenuController in a UICollectionViewCell subclass which is triggered via a UILongPressGestureRecognizer which all works fine and I successfully trigger an NSNotification

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

I catch it in my ViewController and call the following method:

-(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]];
       }
}

And it crashes on the deleteItemsAtIndexPaths: call

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

I've checked everything obvious - like the object from NSNotification and the indexPath created from the indexPathForCell: call and it all seems totally fine. It seems like I'm calling deleteItemsAtIndexPath: with the same information in both places, but for some reason it fails when it goes via the notification route.

This is the info at the address given in the error:

(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)

Perhaps the index path after update being null is significant...

Any ideas?

like image 796
melps Avatar asked Oct 15 '12 10:10

melps


1 Answers

I found a crude but working workaround, and it even checks if action is already implemented in a future release (better than a category)

// 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");
            }
        }
    }
}

Edit: Added check for iOS5.
Edit2: We're shipping that in lots of commercial projects (http://pspdfkit.com) and it works great.

like image 199
steipete Avatar answered Nov 15 '22 21:11

steipete