1. 目标效果
左侧的图片为长按操作前界面的显示效果,右侧的图片为长按“MAC”项右侧的1032E23A34D2(UILabel
) 后,弹出复制选项菜单的显示效果。
2. 实现代码
1. 给要实现长按复制功能的UILabel
添加上下文菜单交互对象:UIContextMenuInteraction
提示:
UIContextMenuInteraction
在iOS 13.0及更新版本中可用。
#import "DeviceInfoViewController.h"
@interface DeviceInfoViewController () <UIContextMenuInteractionDelegate>
@property (nonatomic, weak) IBOutlet UILabel *macLabel;
@property (nonatomic, weak) IBOutlet UILabel *modelLabel;
@end
@implementation DeviceInfoViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
}
- (void)setupUI {
self.title = NSLocalizedString(@"设备信息", nil);
// MAC
[self prepareLongPressCopyInView:self.macLabel];
// 产品型号
[self prepareLongPressCopyInView:self.modelLabel];
}
#pragma mark - 长按弹出复制按钮的相关实现方法
- (void)prepareLongPressCopyInView:(UIView *)view {
view.userInteractionEnabled = YES;
// 通过上下文菜单(UIContextMenuInteraction)实现 (需实现UIContextMenuInteractionDelegate代理方法)
UIContextMenuInteraction *interaction = [[UIContextMenuInteraction alloc] initWithDelegate:self];
[view addInteraction:interaction];
}
2. 实现UIContextMenuInteractionDelegate
代理方法
// MARK: UIContextMenuInteractionDelegate
/// 交互开始时调用, 用来返回 预览控制器 和 操作菜单, 预览控制器 和 操作菜单都可为空
- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction configurationForMenuAtLocation:(CGPoint)location API_AVAILABLE(ios(13.0)) {
// 通过interaction拿到对应的view
UIView *view = interaction.view;
// 创建菜单选项
UIImage *action1Image = nil;
if (@available(iOS 13.0, *)) {
action1Image = [UIImage systemImageNamed:@"doc.on.doc"];
}
UIAction *action1 = nil;
if (view == self.macLabel) {
action1 = [UIAction actionWithTitle:NSLocalizedString(@"复制", nil) image:action1Image identifier:@"App.MenuActionID.Copy.Mac" handler:^(__kindof UIAction * _Nonnull action) {
// 通过系统的粘贴板,记录下需要传递的数据
[UIPasteboard generalPasteboard].string = self.macLabel.text;
}];
} else if (view == self.modelLabel) {
action1 = [UIAction actionWithTitle:NSLocalizedString(@"复制", nil) image:action1Image identifier:@"App.MenuActionID.Copy.Model" handler:^(__kindof UIAction * _Nonnull action) {
// 通过系统的粘贴板,记录下需要传递的数据
[UIPasteboard generalPasteboard].string = self.modelLabel.text;
}];
}
// 创建菜单
UIMenu *menu = [UIMenu menuWithTitle:@"" children:@[action1]];
UIContextMenuConfiguration *config = [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:^UIViewController * _Nullable {
return nil;
} actionProvider:^UIMenu * _Nullable(NSArray<UIMenuElement *> * _Nonnull suggestedActions) {
return menu; // 返回菜单
}];
return config;
}
/// 交互开始时调用, 用来返回预览视图弹出时其所在位置的视图, 例如:如果返回视图A,则预览视图会在视图A位置弹出
/// 不实现该方法或返回nil时, 预览视图会默认在交互所在视图(即添加交互对象的视图)位置弹出
- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)) {
return nil;
}
/// 交互消失时调用, 用来返回预览视图消失时其所在位置的视图, 例如:如果返回视图B,则预览视图会在视图B位置消失
/// 不实现该方法或返回nil时, 预览视图会默认在交互所在视图(即添加交互对象的视图)位置消失
- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForDismissingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)) {
return nil;
}
@end