How can you add a UIGestureRecognizer to a UIBarButtonItem as in the common undo/redo UIPopoverContr

Posted by SG on Stack Overflow See other posts from Stack Overflow or by SG
Published on 2010-04-16T19:30:23Z Indexed on 2010/04/16 19:33 UTC
Read the original article Hit count: 773

Problem

In my iPad app, I cannot attach a popover to a button bar item only after press-and-hold events. But this seems to be standard for undo/redo. How do other apps do this?

Background

I have an undo button (UIBarButtonSystemItemUndo) in the toolbar of my UIKit (iPad) app. When I press the undo button, it fires it's action which is undo:, and that executes correctly.

However, the "standard UE convention" for undo/redo on iPad is that pressing undo executes an undo but pressing and holding the button reveals a popover controller where the user selected either "undo" or "redo" until the controller is dismissed.

The normal way to attach a popover controller is with presentPopoverFromBarButtonItem:, and I can configure this easily enough. To get this to show only after press-and-hold we have to set a view to respond to "long press" gesture events as in this snippet:

UILongPressGestureRecognizer *longPressOnUndoGesture = [[UILongPressGestureRecognizer alloc] 
       initWithTarget:self 
               action:@selector(handleLongPressOnUndoGesture:)];
//Broken because there is no customView in a UIBarButtonSystemItemUndo item
[self.undoButtonItem.customView addGestureRecognizer:longPressOnUndoGesture];
[longPressOnUndoGesture release];

With this, after a press-and-hold on the view the method handleLongPressOnUndoGesture: will get called, and within this method I will configure and display the popover for undo/redo. So far, so good.

The problem with this is that there is no view to attach to. self.undoButtonItem is a UIButtonBarItem, not a view.

Possible solutions

1) [The ideal] Attach the gesture recognizer to the button bar item. It is possible to attach a gesture recognizer to a view, but UIButtonBarItem is not a view. It does have a property for .customView, but that property is nil when the buttonbaritem is a standard system type (in this case it is).

2) Use another view. I could use the UIToolbar but that would require some weird hit-testing and be an all around hack, if even possible in the first place. There is no other alternative view to use that I can think of.

3) Use the customView property. Standard types like UIBarButtonSystemItemUndo have no customView (it is nil). Setting the customView will erase the standard contents which it needs to have. This would amount to re-implementing all the look and function of UIBarButtonSystemItemUndo, again if even possible to do.

Question

How can I attach a gesture recognizer to this "button"? More specifically, how can I implement the standard press-and-hold-to-show-redo-popover in an iPad app?

Ideas? Thank you very much, especially if someone actually has this working in their app (I'm thinking of you, omni) and wants to share...

© Stack Overflow or respective owner

Related posts about cocoa

Related posts about uigesturerecognizer