Allow system UIMenuItems to be reordered

Originator:invalidname
Number:rdar://10259048 Date Originated:10/10/2011
Status:Duplicate/10259071 Resolved:10/12/2011
Product:iPhone SDK Product Version:5.0
Classification:Feature (new) Reproducible:Always
 
Summary:
We need an API to allow apps to customize the order of UIMenuItems, including system items.

Steps to Reproduce:

As documented in -[UIMenuController setMenuItems:], " Custom items appear in the menu after any system menu items."

This is a problem when a system menu item has desirable functionality, but should not receive more prominent placement than the app's custom menu items.

We have an eBook reader that uses UIWebView to render pages.  We've added UIMenuItems to perform highlighting and sticky-noting, similar to the iBooks app.  iOS 5 adds a new system menu item, "Define", which shows a dictionary definition popover.  This is a useful feature, but it is far less important to our end-users than the common highlight and note commands.  However, since it is a system menu item, it appears first in the list of menu items (along with any other menu items, such as "Copy", that we accept our willingness to handle via the canPerformAction:withSender: callback).

Depending on how many menu items we have, and whether we feel the need to suppress menu items by putting a canPerformAction:withSender: in a UIWebView subclass, the define menu item can appear entirely by itself in an oversized button, with all our custom (and more useful) menu items buried behind the right-arrow "page" button on the side of the menu popover.  For us, it is a usability disaster to have the menu popover go into paged mode, putting the less useful "Copy" and "Define" menus on the first page, and burying the app's core functionality on a second or even third page.

We also note that iBooks is somehow able to get around this: it gets a single-page menu popover, with a "Dictionary" menu item that seems to be a synonym for "Define".

We would like to have the Define menu in our app, but not at the cost of our core usability, pushing our essential menu items into a second page.  If we can't put it at the end of the list of menu items, we'd rather not allow it at all.

Expected Results:

Actual Results:

Regression:

Notes:
One workaround is to re-implement system menus.  In the attached project, DefineMenuBuglet, there are #define's to selectively disable the Copy and Define menu items.  There is also a technique for providing a functional equivalent to the system copy menu item, but keeping all the menu items on one page of the popover (like iBooks does).  It does this by suppressing the system "Copy" menu item by catching it in canPerformAction:withSender: in a UIWebView subclass, then adding a custom menu item also called copy (this buglet uses "Copy*" for clarity), whose implementation calls the copy: method from the UIResponderStandardEditActions protocol.

To see this iBooks-like behavior, leave all the #defines in SNFDefineBugletDefines.h on.  To see the (default) paging behavior, comment out #define SUPPRESS_COPY_MENU_ITEM and #define USE_NON_PAGING_COPY_MENU_ITEM, which produces a first page with just the one "Copy" menu item.

This re-implementation of system menu items only works for menu items that make straightforward calls to public methods. By comparison, the "Define" menu item is backed by the non-public _define: method, so we can't use this technique to move a re-implemented "Define" to the end of the list (where it would be more appropriate for our app).

Also, it's totally gross and we wouldn't have to do it if the API would stop treating custom menu items as second-class citizens and instead let us reorder all the menu items, including the system items.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!