如何为UITableViewCell显示自定义UIMenuItem?

时间:2012-09-05 22:47:14

标签: ios uitableview uimenucontroller

我想要在长按UITableViewCell以显示自定义UIMenuItems时弹出UIMenuController。

我在viewDidLoad

中设置了自定义项
UIMenuItem *testMenuItem = [[UIMenuItem alloc] initWithTitle:@"Test" action:@selector(test:)];
[[UIMenuController sharedMenuController] setMenuItems: @[testMenuItem]];

然后我设置了所有正确的委托方法。

- (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;
}

但它只是显示“复制”项目,因为我只允许它和我的自定义项目。但是,自定义项目不会显示。

我意识到,我可以为单元格本身添加一个手势识别器,但这种方式会破坏UIMenuController共享实例的目的,不是吗?

4 个答案:

答案 0 :(得分:51)

据我所知,有两个主要问题:

1)您希望tableView canPerformAction:支持自定义选择器,而文档说它只支持UIResponderStandardEditActions中的两个(复制和/或粘贴);

2)在您通过初始化|| action == @selector(test:)属性添加自定义菜单选项时,不需要部件menuItems。对于此项目选择器,检查将是自动的。

如何显示自定义菜单项并开始工作:

1)使用

修复表视图委托方法

A)

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

b)中

- (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)使用

设置单元格(子类UITableViewCell
-(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 {

}
///////////////////////////////////////////////////////

答案 1 :(得分:8)

为UITableViewCell实现复制和自定义操作:

在您的应用中

一旦,请注册自定义操作:

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()
}

UITableViewCell 子类中,实现自定义方法:

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

UITableViewDelegate 中,实施以下方法:

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()
    }
}

注意:

答案 2 :(得分:2)

仅允许复制第 0 部分的第 0 行的示例

更新到 Swift 5.2

func shouldAllowCopyOn(indexPath: IndexPath) -> Bool {
    if indexPath.section == 0 && indexPath.row == 0 {
       return true
    }
    return false
}

func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
    return self.shouldAllowCopyOn(indexPath: indexPath)
}

func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
    if (action == #selector(UIResponderStandardEditActions.copy(_:))) {
          return self.shouldAllowCopyOn(indexPath: indexPath)
    }
}

func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {
    if (action == #selector(UIResponderStandardEditActions.copy(_:)) && self.shouldAllowCopyOn(indexPath: indexPath)) {
       if let cell = self.tableView.cellForRow(at: indexPath) as? UITableViewCell {
         self.copyAction(cell: cell)
        }
    }
}

@objc
private func copyAction(cell: UITableViewCell) {
    UIPasteboard.general.string = cell.titleLabel.text
}

答案 3 :(得分:1)

SWIFT 3:

在AppDelegate中didFinishLaunchingWithOptions:

let customMenuItem = UIMenuItem(title: "Delete", action:
#selector(TableViewCell.deleteMessageActionTapped(sender:)))
        UIMenuController.shared.menuItems = [customMenuItem]
        UIMenuController.shared.update()
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
   }
}