iOS 16中PDFView自定义编辑菜单及默认菜单移除等技术问题咨询
PDFView 文本编辑菜单相关问题解决方案
1. 获取默认Highlight菜单的动作回调
PDFView的高亮操作属于PDF标注范畴,无法通过常规菜单回调直接捕获,可通过以下两种方式实现监听:
- 监听PDF标注变更通知:
// 在viewDidLoad中注册通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAnnotationChanged:) name:PDFViewAnnotationChangedNotification object:self.pdfView]; // 实现回调处理 - (void)onAnnotationChanged:(NSNotification *)note { PDFAnnotation *annotation = note.userInfo[PDFViewAnnotationKey]; if (annotation.type == PDFAnnotationTypeHighlight) { // 此处处理高亮动作逻辑 NSLog(@"Highlight动作已触发"); } }
- 重写PDFView的addAnnotation方法:自定义PDFView子类,重写
addAnnotation:方法拦截高亮标注的添加操作。
2. 移除默认Highlight等编辑菜单
iOS 15及以下版本
精准匹配对应动作的SEL,在canPerformAction:withSender:中针对性返回NO:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { // 禁用高亮、下划线、删除线等标注动作 if (action == @selector(highlight:) || action == @selector(underline:) || action == @selector(strikeOut:)) { return NO; } // 保留其他需要的系统动作,或直接调用super返回默认值 return [super canPerformAction:action withSender:sender]; }
注意:直接返回NO会禁用所有系统菜单,需精准过滤目标动作。
iOS 16+版本
PDFView的标注类菜单属于内部私有菜单组,无法通过UIMenuBuilder的公开标识符移除,需通过UIEditMenuInteraction完全接管菜单生成逻辑。
3. iOS 16+ 使用UIEditMenuInteraction自定义编辑菜单
是的,iOS16后UIMenuController已废弃,推荐使用UIEditMenuInteraction实现PDFView文本选择的自定义菜单,步骤如下:
- 给PDFView添加交互器:
// 在viewDidLoad中初始化 UIEditMenuInteraction *editMenuInteraction = [[UIEditMenuInteraction alloc] initWithDelegate:self]; [self.pdfView addInteraction:editMenuInteraction];
- 实现
UIEditMenuInteractionDelegate协议:
- (nullable UIMenu *)editMenuInteraction:(UIEditMenuInteraction *)interaction menuForConfiguration:(UIEditMenuConfiguration *)configuration suggestedActions:(NSArray<UIMenuElement *> *)suggestedActions API_AVAILABLE(ios(16.0)) { NSMutableArray<UIMenuElement *> *customMenuElements = [NSMutableArray array]; // 添加自定义Test动作 UIAction *testAction = [UIAction actionWithTitle:@"Test" image:nil identifier:nil handler:^(UIAction * _Nonnull action) { NSLog(@"自定义Test动作触发"); // 获取选中文本 NSString *selectedText = self.pdfView.selectedString; }]; [customMenuElements addObject:testAction]; // 如需保留部分系统动作,从suggestedActions中筛选(示例保留复制动作) for (UIMenuElement *element in suggestedActions) { if ([element isKindOfClass:[UIAction class]]) { UIAction *action = (UIAction *)element; if (action.identifier == UIActionIdentifierCopy) { [customMenuElements addObject:action]; } } } return [UIMenu menuWithChildren:customMenuElements]; } // 控制菜单显示时机(仅选中文本时显示) - (BOOL)editMenuInteraction:(UIEditMenuInteraction *)interaction canShowMenuForConfiguration:(UIEditMenuConfiguration *)configuration API_AVAILABLE(ios(16.0)) { return self.pdfView.selectedString.length > 0; }
4. iOS16+ UIMenuBuilder无法移除Highlight菜单的原因
PDFView的标注类菜单(Highlight、Underline等)属于控件内部私有菜单,未注册到UIMenuStandardEdit等系统公开的菜单标识符下,因此调用removeMenuForIdentifier:无法对其生效,必须通过UIEditMenuInteraction完全自定义菜单。
5. canPerformAction:withSender:失效的原因
iOS16+中系统优先使用UIEditMenuInteraction和UIMenuBuilder构建菜单,canPerformAction:的优先级被降低。对于PDFView这类系统控件,其内部菜单生成逻辑并未完全依赖该方法,因此直接返回NO无法影响私有标注菜单的显示,需结合对应iOS版本的菜单构建方案处理。
内容的提问来源于stack exchange,提问作者Swapnil Rathore
相关产品推荐
相关产品推荐

