iOS开发:如何从UIMenuElement获取触发它的UIButton引用?
核心问题原因
你把sender改成UIButton会报错,是因为触发changeName动作的是UIMenuElement(具体是UIAction实例),而非按钮本身,类型不匹配直接导致崩溃。要拿到按钮的Tag,得在创建菜单时就把Tag和菜单动作绑定。
方案1:用UIAction的userInfo存储Tag
创建菜单时,给每个UIAction的userInfo字段存入对应按钮的Tag,后续从动作实例中读取:
// 生成带Tag绑定的菜单 func makePopUpMenu(forButtonTag tag: Int) -> UIMenu { // 定义菜单选项动作,把Tag存入userInfo let renameAction = UIAction(title: "修改名称") { [weak self] action in self?.changeName(action: action) } renameAction.userInfo = ["buttonTag": tag] // 其他菜单选项同理 let deleteAction = UIAction(title: "删除", attributes: .destructive) { [weak self] action in self?.deleteItem(action: action) } deleteAction.userInfo = ["buttonTag": tag] return UIMenu(title: "", children: [renameAction, deleteAction]) } // 给按钮绑定菜单 override func viewDidLoad() { super.viewDidLoad() button1.menu = makePopUpMenu(forButtonTag: button1.tag) button1.showsMenuAsPrimaryAction = true button2.menu = makePopUpMenu(forButtonTag: button2.tag) button2.showsMenuAsPrimaryAction = true // button3、button4重复上述操作 } // 处理菜单选择的方法 func changeName(action: UIAction) { // 从userInfo中取出按钮Tag guard let buttonTag = action.userInfo?["buttonTag"] as? Int else { return } // 根据Tag操作对应数组位置 guard buttonTag < yourDataArray.count else { return } yourDataArray[buttonTag] = "新的名称" }
方案2:创建菜单时直接捕获Tag(更简洁)
如果不需要从UIMenuElement中额外获取其他信息,可以直接在创建动作时捕获按钮的Tag,跳过从sender读取的步骤:
func makePopUpMenu(forButtonTag tag: Int) -> UIMenu { let renameAction = UIAction(title: "修改名称") { [weak self] _ in // 直接用捕获的Tag操作数组 guard tag < self?.yourDataArray.count ?? 0 else { return } self?.yourDataArray[tag] = "新的名称" } return UIMenu(title: "", children: [renameAction]) } // 按钮绑定菜单的代码和方案1一致
两种方案都能解决你的问题,方案2代码更简洁,方案1保留了从动作实例读取信息的灵活性,可根据需求选择。
内容的提问来源于stack exchange,提问作者user14337541
相关产品推荐
相关产品推荐

