选中UIMenuItem时能否阻止UIMenuController自动收起?
可以通过iOS公有API实现该效果,完全符合App Store审核规则,无需调用私有接口。
实现原理
UIMenuController默认的自动收起逻辑,是在菜单项绑定的action方法执行完成后,系统自动触发隐藏操作。只要在自定义的菜单项action方法执行结束前,主动调用setMenuVisible:animated:方法将菜单重新设置为显示状态,就能覆盖系统的默认隐藏行为。
具体实现步骤
- 首先自定义需要保持菜单展开的UIMenuItem,绑定自定义响应方法
// 示例:添加缩进菜单项 UIMenuItem *indentItem = [[UIMenuItem alloc] initWithTitle:@"缩进" action:@selector(increaseIndent:)]; [UIMenuController sharedMenuController].menuItems = @[indentItem];
- 在自定义响应方法中,业务逻辑执行完成后主动唤起菜单
- (void)increaseIndent:(UIMenuItem *)sender { // 执行业务逻辑,如调整文本缩进 [self adjustTextIndent]; // 若操作后文本选中区域发生变化,需重新设置菜单位置 CGRect newSelectionRect = [self currentSelectionRect]; [[UIMenuController sharedMenuController] setTargetRect:newSelectionRect inView:self]; // 主动设置菜单为显示状态,覆盖系统默认隐藏逻辑 [[UIMenuController sharedMenuController] setMenuVisible:YES animated:NO]; }
Swift 对应实现:
// 添加缩进菜单项 let indentItem = UIMenuItem(title: "缩进", action: #selector(increaseIndent(_:))) UIMenuController.shared.menuItems = [indentItem] // 响应方法实现 @objc func increaseIndent(_ sender: UIMenuItem) { // 执行业务逻辑 adjustTextIndent() // 选中区域变化时重新定位菜单 let newSelectionRect = currentSelectionRect() UIMenuController.shared.setTargetRect(newSelectionRect, in: self) // 保持菜单显示 UIMenuController.shared.setMenuVisible(true, animated: false) }
注意事项
- 执行操作后需确保持有菜单的视图仍然保持第一响应者状态,第一响应者变更会导致菜单被系统自动收回
- 若操作未改变选中区域的位置和大小,可以跳过重新设置
targetRect的步骤 - 上述用到的所有API从iOS 3.0开始就属于公开接口,不存在审核风险,备忘录等系统应用的对应逻辑也是基于该方案实现的
内容的提问来源于stack exchange,提问作者Artium
相关产品推荐
相关产品推荐

