Search code examples
objective-cuicollectionviewuimenucontrolleruimenuitem

Can't get UIMenuController to show custom items


So, I am not sure if I am doing something wrong here, but I have a UIViewController that has a UICollectionView on it. In the UIViewController's viewDidLoad method, I do the following it doesn't add any custom menu items to the popup that shows up.

UIMenuItem *removeItem = [[UIMenuItem alloc] initWithTitle:@"Remove" action:@selector(handleRemoveItem:)];
UIMenuItem *duplicateItem = [[UIMenuItem alloc] initWithTitle:@"Duplicate" action:@selector(handleDuplicateItem:)];

[[UIMenuController sharedMenuController] setMenuItems:@[removeItem, duplicateItem]];

[removeItem release];
[duplicateItem release];

I did set the collectionView:shouldShowMenuForItemAtIndexPath: and the collectionView:canPerformAction:forItemAtIndexPath:withSender: to return YES under all circumstances, but no matter what, only Cut, Copy, and Paste will show up.

Did I not implement this fully, or did I not do it right?

P.S. - I did look at as many examples as I could throughout google and I didn't find anything that helped.


Solution

  • You are correct. It is impossible to customize the menu that appears when you do a long press on a table view cell or collection view cell.

    I discuss the problem in my book:

    http://www.apeth.com/iOSBook/ch21.html#_table_view_menus

    As I say there, Copy, Cut and Paste are the only choices you can have. You will have to make the menu emanate from something else if you want to customize it.

    EDIT: In the iOS 7 version of my book, I demonstrate a way to do this. It's the same for table view cells and collection view cells, so I'll start with the table view cell solution. The trick is that you must implement the action method in a cell subclass. For example, if your custom action selector is abbrev:, you must subclass the cell and implement abbrev::

    https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch08p454tableCellMenus2/ch21p718sections/MyCell.m

    That's the only tricky part. Then, back in your controller class, you do for abbrev: exactly what you would do for any menu. In shouldShowMenuForRowAtIndexPath:, add it to the custom menu. Then implement canPerformAction: and performAction: just as you would expect (scroll all the way to the bottom):

    https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch08p454tableCellMenus2/ch21p718sections/RootViewController.m

    Here's the parallel implementation for collection view cells: the cell subclass:

    https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch08p466collectionViewFlowLayout2/ch21p748collectionViewFlowLayout2/Cell.m

    And the controller (scroll all the way to the bottom):

    https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch08p466collectionViewFlowLayout2/ch21p748collectionViewFlowLayout2/ViewController.m

    Those approaches are also translated into Swift (not without some difficulty) in the iOS 8 edition of my book.