iOS:UIMenu 导致按钮操作仅触发一次。之后,每个后续的单击按钮操作都不会触发

iOS: UIMenu is causing the button action to trigger only once. After that every subsequent click button action is not triggering

提问人:Logger 提问时间:11/7/2023 最后编辑:Logger 更新时间:11/7/2023 访问量:58

问:

我有一个UIButon,并与之关联了一个UIMenu。单击显示 UIMenu 的按钮后。但是我可以观察到导致显示菜单的按钮操作仅调用一次,之后每个后续单击按钮操作都不会触发。可能是 UIMenu 以这样一种方式缓存按钮操作,即特定按钮操作仅调用一次。但是根据我的要求,每次单击按钮时都必须触发按钮操作。

下面我发布了示例代码,每次用户单击菜单选项时,我都尝试在控制台上打印随机数,并且每次打印相同的数字时我都可以看到。这是因为这段代码只在第一次调用 let randomNumber = Int(arc4random_uniform(10))

*导入 UIKit 类 ViewController: UIViewController {

var name = String()
var namesText = ["one", "Two", "Three", "Four", "Five", "six", "Seven","Eight", "Nine", "Ten"]

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
}

@IBAction func buttonNewAction(_ sender: UIButton) {
        self.showMenu(sender: sender)
}

func showMenu(sender: UIButton) {
    let randomNumber = Int(arc4random_uniform(10))
        
    let usersItem = UIAction(title: "Users", image: UIImage(systemName: "person.fill")) { (action) in
        print("\(randomNumber) in User action")
    }
    
    let addUserItem = UIAction(title: "Add User", image: UIImage(systemName: "person.badge.plus")) { (action) in
        print("\(randomNumber) in add user action")
    }
    
    let removeUserItem = UIAction(title: "Remove User", image: UIImage(systemName: "person.fill.xmark.rtl")) { (action) in
        print("\(randomNumber) in Remove user")
    }
    
    let menu = UIMenu(title: "", children: [usersItem, addUserItem, removeUserItem])
    sender.menu = menu
    sender.showsMenuAsPrimaryAction = true
}

}*

iOS Swift iPhone SwiftUI UI菜单

评论


答:

1赞 son 11/7/2023 #1

不能按子类 UIButton 重新分配按钮的菜单。然后重写 UIControl 委托,以在每次关闭菜单弹出框时删除 UIMenu 属性。contextMenuInteraction willEnd

更新:当您期待 UIMenu 时,始终在关闭时进行设置。当从 Button 的子类中删除 UIMenu 时,我做了一个技巧来处理回调,然后再次设置点击动作,因为只工作一次。.menuActionTriggered

class MenuButton: UIButton {
    var onRemovedMenu: (() -> Void)?

    override func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willEndFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) {
        super.contextMenuInteraction(interaction, willEndFor: configuration, animator: animator)
        removeMenuWhenDismissed()
    }
    
    private func removeMenuWhenDismissed() {
        self.menu = nil
        onRemovedMenu?()
    }
}

class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = MenuButton()
        button.showsMenuAsPrimaryAction = true
        button.onRemovedMenu = { [weak self] in
            //put delay to avoid warning log when dismissing and adding menu too close
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {                
                self?.setupButton(button)
            }
        }
        
        button.setTitle("TAP ME", for: .normal)
        button.setTitleColor(.blue, for: .normal)
        setupButton(button)
        
        view.addSubview(button)
        button.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
        button.center = view.center
    }

    private func setupButton(_ button: MenuButton) {
        button.menu = UIMenu(title: "")
        //UIControler.Event to `menuActionTriggered`
        button.addTarget(self, action: #selector(self.showMenu), for: .menuActionTriggered)
    }
    ...
}

最终结果:

enter image description here

评论

0赞 Logger 11/7/2023
菜单按钮操作调用正常。但是我希望按钮操作func showMenu(sender: UIButton)始终在“TAP ME”按钮单击上调用。实际上,每次单击 TAPME 按钮时都必须触发此行( let randomNumber = Int(arc4random_uniform(10)) )。
0赞 son 11/7/2023
@Logger我编辑了答案,你可以看看。
0赞 Logger 11/7/2023
谢谢,它按预期工作。感谢您抽出宝贵时间研究它。干杯
1赞 son 11/7/2023
很高兴我能帮助xD