ios - ¿Cómo mostrar un UIMenuItem personalizado para una UITableViewCell?
uimenucontroller (3)
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 delegados 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 {
}
///////////////////////////////////////////////////////
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 delegados 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?
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
}
}