iOS 14 在打开之前设置 UIBarButttonItem 菜单

iOS 14 setup the UIBarButttonItem menu before it is opened

由于 iOS14 提供了一种在 UIBarButtonItem 上设置菜单的简单方法,我想知道我是否想念没有简单的方法来设置其项目,因为它们可能取决于当前上下文.

我看到有 UIDeferredMenuElement,但这似乎不是一个很好的用例?

我也看到有 primaryAction,但似乎没有从那里调用菜单的简单方法。

第三个选项似乎是根据可能影响它的每个更改重新调整菜单,但这似乎不是一个好主意。

我想我错过了什么。

基本上对于一个简单的条形按钮项目没有这样的规定。像 UIButton 这样的 UIControl 有一个事件 .menuActionTriggered,此时构造菜单并将其分配给控件是完全合理的,从而实现一个在菜单出现之前瞬间构造的动态菜单.

但是您不能使用条形按钮项来执行此操作 — 除非它是一个带有 UIButton 的自定义视图条形按钮项。

否则您需要做的是通过一些 other 机制观察周围的情况,并在每次情况发生变化时更改条形按钮项目的菜单。这听起来很痛苦,但这可能是您唯一的选择。 (我认为这正是你所说的“第三个选项似乎是对可能影响它的每个更改重新调整菜单,但这似乎不是一个好主意。”)

我认为你的要求是合理的,没有规定似乎有点愚蠢;如果您有好的用例,我建议您向 Apple 提交增强请求。

这是 Swift 5 版本的实现,灵感来自@matt 的回答。

private func setButton() {
    button.menu = UIMenu() // Here must be a placeholder menu. As the menu won't show if button.menu is nil.
    button.showsMenuAsPrimaryAction = true
    button.addTarget(self, action: #selector(createMenu(_:)), for: .menuActionTriggered)
}

@objc private func createMenu(_ button:UIButton) {
    ...
}

这是目前唯一的解决方案。因为 func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) 不会每次都调用,除非您在按钮设置为 showsMenuAsPrimaryAction = true 时按住一会儿。

----已编辑----

如果我的回答是正确的,马特也是。因为我的代码是基于他的想法。所以我一开始并不认为马特是错的。我只是觉得提问者对matt的回答有误解