如何检测UIMenu被dismiss(关闭)的时机
方案1:使用 Context Menu Interaction 代理(适配iOS14+,覆盖所有UIMenu触发场景)
不管你是将UIMenu绑定为长按触发还是点击触发(showsMenuAsPrimaryAction = YES),都可以通过实现UIContextMenuInteractionDelegate的结束回调来监听关闭事件:
- 首先给你的UIButton绑定菜单并添加交互代理:
// Objective-C 示例 self.button.showsMenuAsPrimaryAction = YES; self.button.menu = [UIMenu menuWithChildren:@[/* 你的菜单选项 */]]; [self.button addInteraction:[UIContextMenuInteraction interactionWithDelegate:self]];
// Swift 示例 button.showsMenuAsPrimaryAction = true button.menu = UIMenu(children: [/* 你的菜单选项 */]) button.addInteraction(UIContextMenuInteraction(delegate: self))
- 然后实现代理的结束方法,这里就是菜单关闭的触发时机:
- (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction willEndForConfiguration:(UIContextMenuConfiguration *)configuration animator:(id<UIContextMenuInteractionAnimating>)animator { // 菜单即将关闭,在这里执行移除按钮的逻辑 [self.button removeFromSuperview]; }
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willEndFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) { // 菜单即将关闭,执行移除按钮逻辑 button.removeFromSuperview() }
注意:这个方法不管用户是点击菜单外部区域关闭,还是点击菜单项后自动关闭都会触发,完全匹配需求。
方案2:iOS16+ 极简方案
如果你的App最低支持iOS16,可以直接使用UIButton新增的menuPresentationDelegate回调监听关闭事件:
button.menuPresentationDelegate = self // 实现代理方法 func menuPresentationControllerDidDismiss(_ controller: UIMenuPresentationController) { // 菜单已经关闭,执行对应逻辑 button.removeFromSuperview() }
避坑提示
- 不要尝试监听私有通知或者私有类的生命周期,后续系统版本迭代很容易失效
- 上述两个方案都不需要监听菜单弹出事件,只会在关闭时触发回调
内容的提问来源于stack exchange,提问作者Ungrace
相关产品推荐
相关产品推荐

