¿Cómo mostrar un UIMenuItem personalizado para una UITableViewCell?

Quiero el UIMenuController que aparece cuando presiono una UITableViewCell para mostrar UIMenuItems personalizados.

Configuré el artículo personalizado en viewDidLoad

UIMenuItem *testMenuItem = [[UIMenuItem alloc] initWithTitle:@"Test" action:@selector(test:)]; [[UIMenuController sharedMenuController] setMenuItems: @[testMenuItem]]; 

Y luego configuro todos los métodos delegates correctos.

 - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } -(BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { return (action == @selector(copy:) || action == @selector(test:)); } - (BOOL)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { if (action == @selector(copy:)) { // do stuff } return YES; } 

Pero todo lo que hace es mostrar el elemento “Copiar”, ya que solo lo permito y mi artículo personalizado. El artículo personalizado, sin embargo, no aparecerá.

Me doy cuenta de que podría agregar un reconocedor de gestos a la celda en sí, pero ese tipo de derrota el propósito de la instancia compartida de UIMenuController, ¿no?

Por lo que yo entiendo, hay dos problemas principales:

1) espera tableView canPerformAction: para admitir selectores personalizados, mientras que la documentación dice que solo admite dos de UIResponderStandardEditActions (copiar y / o pegar);

2) no hay necesidad de la parte || action == @selector(test:) || action == @selector(test:) mientras agrega las opciones de menú personalizadas al inicializar la propiedad menuItems . Para estos selectores de artículos, el cheque será automático.

Lo que puede hacer para que se muestre el elemento de menú personalizado y el trabajo es:

1) Corregir los métodos delegates de vista de tabla con

un)

 UIMenuItem *testMenuItem = [[UIMenuItem alloc] initWithTitle:@"Test" action:@selector(test:)]; [[UIMenuController sharedMenuController] setMenuItems: @[testMenuItem]]; [[UIMenuController sharedMenuController] update]; 

segundo)

 - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } -(BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { return (action == @selector(copy:)); } - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { // required } 

2) Configure las celdas (subclases de UITableViewCell ) con

 -(BOOL) canPerformAction:(SEL)action withSender:(id)sender { return (action == @selector(copy:) || action == @selector(test:)); } -(BOOL)canBecomeFirstResponder { return YES; } /// this methods will be called for the cell menu items -(void) test: (id) sender { } -(void) copy:(id)sender { } /////////////////////////////////////////////////////// 

Para implementar copy y una acción personalizada para UITableViewCell:

Una vez que esté en su aplicación, registre la acción personalizada:

 struct Token { static var token: dispatch_once_t = 0 } dispatch_once(&Token.token) { let customMenuItem = UIMenuItem(title: "Custom", action: #selector(MyCell.customMenuItemTapped(_:)) UIMenuController.sharedMenuController().menuItems = [customMenuItem] UIMenuController.sharedMenuController().update() } 

En su subclase UITableViewCell , implemente el método personalizado:

 func customMenuItemTapped(sender: UIMenuController) { // implement custom action here } 

En su UITableViewDelegate , implemente los siguientes métodos:

 override func tableView(tableView: UITableView, shouldShowMenuForRowAtIndexPath indexPath: NSIndexPath) -> Bool { return true } override func tableView(tableView: UITableView, canPerformAction action: Selector, forRowAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool { return action == #selector(NSObject.copy(_:)) || action == #selector(MyCell.customMenuItemTapped(_:)) } override func tableView(tableView: UITableView, performAction action: Selector, forRowAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) { switch action { case #selector(NSObject.copy(_:)): // implement copy here default: assertionFailure() } } 

Notas:

  • Esto usa los nuevos #Selector de Swift 3 .
  • Consulte esta respuesta para obtener información sobre cómo implementar la copia .

SWIFT 3:

En AppDelegate didFinishLaunchingWithOptions:

 let customMenuItem = UIMenuItem(title: "Delete", action: #selector(TableViewCell.deleteMessageActionTapped(sender:))) UIMenuController.shared.menuItems = [customMenuItem] UIMenuController.shared.update() 

en su clase TableViewContoller:

 override func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool { return true } override func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool { return action == #selector(copy(_:)) || action == #selector(TableViewCell.yourActionTapped(sender:)) } override func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) { if action == #selector(copy(_:)) { let pasteboard = UIPasteboard.general pasteboard.string = messages[indexPath.row].text } }