在 AppDelegate 中调用 buildMenu 而不是 UIViewController
Posted
技术标签:
【中文标题】在 AppDelegate 中调用 buildMenu 而不是 UIViewController【英文标题】:buildMenu is called in AppDelegate but not UIViewController 【发布时间】:2019-12-05 18:50:43 【问题描述】:我正在尝试为我的应用程序中的每个视图创建一个自定义菜单,但是在视图控制器中似乎没有调用 buildMenu。这是一个例子:
在我的 AppDelegate 中,使用了此代码,它 100% 正常工作。
override func buildMenu(with builder: UIMenuBuilder)
print("Updating menu from AppDelegate")
super.buildMenu(with: builder)
let command = UIKeyCommand(
input: "W",
modifierFlags: [.command],
action: #selector(self.helloWorld(_:))
)
command.title = "Hello"
builder.insertChild(UIMenu(
__title: "World",
image: nil,
identifier: UIMenu.Identifier(rawValue: "com.hw.hello"),
options: [],
children: [command]
), atEndOfMenu: .file)
@objc private func helloWorld(_ sender: AppDelegate)
print("Hello world")
但是我需要根据用户在应用程序中的位置更改菜单中可用的选项,因此我尝试在 UIViewController 中执行此操作:
override func viewDidAppear(_ animated:Bool)
// Tried all of these to see if any work
UIMenuSystem.main.setNeedsRebuild()
UIMenuSystem.context.setNeedsRebuild()
UIMenuSystem.main.setNeedsRevalidate()
UIMenuSystem.context.setNeedsRevalidate()
又一次……
// This is never called
override func buildMenu(with builder: UIMenuBuilder)
print("Updating menu in View Controller")
但 UIViewController 中的 buildMenu 永远不会被调用 :(
如果这是预期行为或是否有任何解决方法,您有什么想法吗?
【问题讨论】:
不确定你要重建菜单做什么,但你可以在视图控制器中使用validateCommand:
方法来动态更新菜单选项(即禁用/启用命令或更改其标题)。
【参考方案1】:
对于主菜单,系统只参考UIApplication
和UIApplicationDelegate
,因为主菜单可以在没有任何窗口的情况下存在,因此没有任何UIViewController
层次结构。这就是为什么主菜单不会调用您对 UIViewController
的覆盖。
对于上下文菜单,系统会从视图开始查询完整的响应者链。
如果您需要根据上下文更新主菜单命令:
您可以将buildMenu(with:)
留在UIApplicationDelegate
中,安排代表找出发生变化的时间和内容,并在发生变化时致电UIMenuSystem.main.setNeedsRebuild()
,或者
您可以在UIViewController
子类中定义一个私有方法buildMyMenu(with:)
,并安排UIApplicationDelegate
中的buildMenu(with:)
调用它,或者
您可以在buildMenu
中构建一个静态菜单,并依靠您对canPerformAction(_:withSender:)
和validate(_:)
的覆盖来启用或禁用甚至隐藏特定命令,例如通过更新 validate(_:)
覆盖中的 attributes
属性。
【讨论】:
您对此有什么想法:forums.developer.apple.com/thread/124710 ?【参考方案2】:这是预期的行为。引用docs:
由于菜单可以存在没有窗口或视图层次结构,系统仅咨询
UIApplication
和UIApplicationDelegate
来构建应用程序的菜单栏。
同样的docs page 解释了如何从视图控制器调整菜单命令,还有一个很棒的示例项目,所以一定要检查它。
【讨论】:
以上是关于在 AppDelegate 中调用 buildMenu 而不是 UIViewController的主要内容,如果未能解决你的问题,请参考以下文章
如何在appdelegate中调用viewController的方法
Cordova iOS:在 AppDelegate.m 中添加方法调用
无法从 AppDelegate 调用 ViewController 方法