iOS 17弹窗式UIButton如何通过代码修改选中项?
你原来的方法需要重新创建Menu并赋值,确实不够简洁。这里有两种更合理的方式,不需要重复构建Menu:
方法一:保存UIAction数组的引用(推荐)
初始化时把生成的UIAction数组存为实例变量,之后直接修改对应项的状态即可,UIMenu会自动同步UI:
// 把UIAction数组声明为实例变量,不要放在局部作用域里 var menuActions: [UIAction]! override func viewDidLoad() { super.viewDidLoad() let itemTitles = ["Horse","Dog","Cat","Budgie"] menuActions = itemTitles.map { title in UIAction(title: title) { [weak self] _ in // 这里写点击后的处理逻辑 } } // 初始化选中第3项(索引2) menuActions[2].state = .on popupButton.menu = UIMenu(children: menuActions) } // 运行时调用这个方法修改选中项 func setSelectedMenuItem(at index: Int) { // 单选场景下先清空所有选中状态(多选可跳过这步) menuActions.forEach { $0.state = .off } // 边界检查,防止数组越界 guard index >= 0 && index < menuActions.count else { return } menuActions[index].state = .on }
调用setSelectedMenuItem(at: 3)就能直接把选中项切换到"Budgie",完全不用重新设置Menu。
方法二:直接从现有Menu中查找修改(无引用时)
如果没保存UIAction数组的引用,也可以直接从按钮的Menu里找到对应项修改,同样不需要重构Menu:
func setSelectedMenuItem(at index: Int) { guard let menu = popupButton.menu, let actions = menu.children as? [UIAction], index >= 0 && index < actions.count else { // 处理Menu为空、类型转换失败或索引越界的情况 return } // 单选场景重置所有选中状态 actions.forEach { $0.state = .off } actions[index].state = .on }
核心原理
UIAction的state属性是可变的,修改后对应的UIMenu会自动更新显示,根本不需要重新创建Menu并赋值给按钮——这是你原来方法冗余的关键原因。如果是多选需求,直接修改单个action的state即可,不用清空其他项。
内容的提问来源于stack exchange,提问作者Fattie
相关产品推荐
相关产品推荐

