复制 粘贴 全选 添加 拷贝 UIMenuController的使用

本文介绍如何在iOS应用中实现长按菜单功能,包括为UILabel和UITableViewCell添加标准及自定义菜单项的过程。通过子类化和实现特定方法,开发者可以轻松地为应用中的元素添加上下文敏感的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1, 基本使用
以对一个UILabel长按弹出菜单为例

子类化UILabel
因为需要覆盖这几个方法:
- (BOOL)canBecomeFirstResponder; 返回YES
同时需要在每次UI元素出现的时候去becomeFirstResponder一次,才能显示出菜单. 在我的实测中, 我在ViewDidLoad里面这么做了, 当UI导航到别的页面(导航控件, 或modal页面), 然后回来, 菜单又失效了, 所以我写到ViewWillAppear里面去了, 通过

  • (BOOL)canPerformAction:(SEL)action withSender:(nullable id)sender;
    这个方法会在每一个menuItem生成的时候调用一次, 因此在方法体里就要根据action来判断是否需要显示在菜单里, 如果不需要, 则返回NO. 也就是说, 如果你什么都不做, 直接返一个YES, 那么所有的默认菜单项都会显示出来, 此处我们只要一个Copy选项吧:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    return (action == @selector(copy:));
}

添加触发方式
如果是以长按为触发, 则添加长按手势, 代码片段如下:

// 在awakeFromNib里面添加即可
UILongPressGestureRecognizer *menuGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(menu:)];
    menuGesture.minimumPressDuration = 0.2;
    [self addGestureRecognizer:menuGesture];

- (void)menu:(UILongPressGestureRecognizer *)sender {
    if (sender.state == UIGestureRecognizerStateBegan) {
        UIMenuController *menu = [UIMenuController sharedMenuController];
        [menu setTargetRect:self.frame inView:self.superView]; // 把谁的位置告诉控制器, 菜单就会以其为基准在合适的位置出现
        [menu setMenuVisible:YES animated:YES];
    }
}

编写菜单行为
上面我们只要了copy, 那么就覆盖默认的copy方法:

- (void)copy:(id)sender {
    UIPasteboard *paste = [UIPasteboard generalPasteboard];
    paste.string = self.text;
}

2, 添加自定义菜单项
自定义菜单只需要在菜单控制器添加几个item即可, 结合上例, 我的那个label是显示电话号码的, 那么就让它多显示一个”打电话”和一个”发短信”菜单吧, 唯一需要注意的是, 在设置自定义菜单项时, 设置的items只影响自定义部分, 标准菜单项仍然是由canPerformAction决定的:

UIMenuItem *itemCall = [[UIMenuItem alloc] initWithTitle:@"Call" action:@selector(call:)];
UIMenuItem *itemMessage = [[UIMenuItem alloc] initWithTitle:@"Message" action:@selector(message:)];
[[UIMenuController sharedMenuController] setMenuItems: @[itemCall, itemMessage]];
[[UIMenuController sharedMenuController] update];

注, 添加了两个菜单后, canPerformAction需要相应变化, 自己想想应该怎么改. 也可以在下一节看代码. 当然也要自行写完里面的call和message方法, 参照copy的写法即可

3, UITableViewCell长按显示菜单
标准菜单项
UITableView里面长项条目显示标准菜单, 只需要实现下述代理方法即可:

- (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:)); // 只显示Copy
}

- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    if (action == @select(copy:)) {
        UIPasteboard *paste = [UIPasteboard generalPasteboard];
        paste.string = cell.detailLabel.text; // 自行写业务逻辑
    }
}

4, TableViewCell添加自定义菜单项
同样也得子类化一个TableViewCell,目的也是为了覆盖同样的几个方法:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    return (action == @selector(copy:) || action == @selector(call:) || action == @selector(message:)); // 此处我们把三个行为都写全了, 回答上一节的问题
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

但因为tableView已经实现了菜单, 所以不需要显式为每个cell去becomeFirtResponder了.

添加菜单项的方法同上, 写菜单行为的方法同copy:, 都是一样的.注: 你们或许已经发现了, 添加自定义菜单项的时候, 仍然需要canPerformAction, 在这里, 与tableView代理里面的同名方法有什么关系? 是的, 两个都要写, tableView里面的只会影响标准菜单, 文档说只支持这两个UIResponderStandardEditActions (copy/paste)

注: 然而, - (void)tableView:(UITableView )tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath )indexPath withSender:(id)sender这个方法却有点别扭, 一来不需要去实现了, 二来又不能注释掉(你们自己试一下), 等于一定要留一个空的方法体在那里…

文/walkerwzy(简书作者)
原文链接:http://www.jianshu.com/p/4505efaa0919
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

<think>我们正在处理用户关于Vim全选复制粘贴操作的问题。根据引用内容,我们可以总结如下:1.全选:在命令模式下,先按`gg`跳到文件首行,然后按`v`(小写v)进入可视模式,再按`G`(大写G)跳到文件末行,这样就全选了。2.复制全选后,按`y`进行复制(yank)。3.粘贴:按`p`(小写p)在光标后粘贴,或按`P`(大写P)在光标前粘贴。但是注意,引用中提到了几种不同的方法,有些是直接使用命令,有些是使用寄存器。另外,引用[3]提到可以使用`"+y`将内容复制到系统剪贴板,这样可以在其他程序中粘贴。因此,我们需要给用户提供两种情况的解决方案:-在Vim内部进行复制粘贴使用Vim的寄存器)-复制到系统剪贴板(以便在其他程序中使用)同时,用户还提到了全选删除和全选剪切的操作,我们也一并说明。步骤:1.全选:-命令模式(按Esc)->gg(跳到首行)->V(大写V,进入行可视模式)->G(跳到末行)或者或者使用:ggvG或ggVG(小写v是进入可视模式,大写V是行可视模式,G是跳到最后一行)注意:在可视模式下,选中的内容会高亮显示。2.复制:-在选中状态下,按`y`复制到Vim的默认寄存器(即无名寄存器)。-如果想复制到系统剪贴板(以便在其他程序中使用),则按`"+y`(先按双引号,再按加号,再按y)。注意:这个功能需要Vim支持clipboard,可以通过`vim--version|grepclipboard`查看是否支持。如果不支持,可能需要安装支持clipboard的Vim版本。3.删除或剪切:-在选中状态下,按`d`会删除选中内容(同时这些内容会被保存到寄存器,相当于剪切)。-按`x`也可以删除,但通常`d`在可视模式下更常用。4.粘贴:-在命令模式下,将光标移动到要粘贴的位置,按`p`在光标后粘贴,按`P`在光标前粘贴。-如果是复制到系统剪贴板的内容,则可以在其他程序中粘贴。如果是从其他程序复制的内容,在Vim中可以使用`"+p`来粘贴(从系统剪贴板粘贴)。另外,引用[2]和[4]提到了一种快速全选复制的方法:`ggyG`。解释一下:-gg:跳转到首行-yG:从当前行复制到文件末尾(G代表文件末尾)但是这种方法没有进入可视模式,直接通过命令复制。我们给用户提供两种全选复制的方法(可视模式方法和命令方法),并说明剪切、删除和粘贴。同时,注意用户可能需要在Vim内部操作,也可能需要与系统剪贴板交互。因此,回答结构如下:1.全选操作(两种方式)2.复制操作(Vim内部寄存器和系统剪贴板)3.剪切和删除操作4.粘贴操作(Vim内部和系统剪贴板)最后,生成相关问题。注意:用户可能使用的是Ubuntu系统,所以我们在回答中也可以提到如何检查Vim是否支持clipboard(如引用[3]和[4]中提到的系统剪贴板操作需要支持)。引用来源:根据用户提供的引用,我们引用[1][2][3][4]来支持我们的步骤。</think>### Vim 全选复制粘贴操作指南 在 Vim 中进行全选复制粘贴的操作步骤如下(所有操作均在**命令模式**下进行,按 `Esc` 可确保进入命令模式): #### 1. **全选操作** - **方法 1(可视模式):** ```bash ggvG # 或 ggVG ``` - `gg`:跳转到文件首行 - `v`:进入**字符可视模式**(`V` 进入行可视模式) - `G`:跳转到文件末行 *效果:全选内容高亮显示[^2][^4]。* - **方法 2(直接命令):** ```bash :%y # 复制全文到寄存器 ``` #### 2. **复制操作** - **复制到 Vim 寄存器:** 全选后按 `y`(yank),内容存入 Vim 默认寄存器[^1][^3]。 ```bash ggvGy # 全选复制 ``` - **复制到系统剪贴板:** 全选后按 `"+y`,内容存入系统剪贴板(需 Vim 支持 `+clipboard`)[^3]。 ```bash ggvG"+y # 复制到系统剪贴板 ``` #### 3. **粘贴操作** - **粘贴 Vim 寄存器内容:** 按 `p`(光标后粘贴)或 `P`(光标前粘贴)[^1]。 ```bash p # 粘贴 ``` - **粘贴系统剪贴板内容:** 按 `"+p` 粘贴系统剪贴板内容[^3]。 ```bash "+p # 粘贴系统剪贴板 ``` #### 4. **全选删除/剪切** - **删除(剪切):** 全选后按 `d`(删除内容存入寄存器,可粘贴)[^2][^4]。 ```bash ggvGd # 全选删除(剪切) ``` - **直接清空文件:** ```bash :%d # 删除全文 ``` #### 注意事项 1. **行数限制:** 默认复制行数上限为 50 行,修改 `~/.vimrc` 可调整(例如 `set viminfo='1000,<300` 改为 300 行)[^1]。 2. **系统剪贴板支持:** 通过 `vim --version | grep clipboard` 检查 `+clipboard` 支持。若无,需安装完整版 Vim(如 `sudo apt install vim-gtk`)。 --- ### 相关问题 1. Vim 中如何将复制的内容粘贴到系统其他应用程序? 2. 如何解决 Vim 跨文件复制时的行数限制问题? 3. Vim 可视模式(Visual Mode)下有哪些高效编辑技巧? 4. 如何配置 Vim 使其默认支持系统剪贴板操作? [^1]: Vim 全选复制行数限制解决方法 [^2]: Vim 全选删除与复制命令 [^3]: Vim 系统剪贴板操作与寄存器使用 [^4]: Vim 全选高亮与操作命令
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值