NoneBuild Menu вызывается в AppDelegate, но не UIViewController

Я пытаюсь создать пользовательское меню для каждого представления в моем приложении, однако кажется, что buildMenu не вызывается в View Controllers. Вот пример:

В моем 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")
}

но buildMenu в UIViewController никогда не вызывается:(

Есть идеи, если это предполагаемое поведение или есть какие-то обходные пути?

1 ответ

Для основных меню система только консультируется UIApplication а также UIApplicationDelegate, поскольку основные меню могут существовать без какого-либо окна и, следовательно, без каких-либо UIViewController иерархия. Вот почему ваше переопределение на UIViewController не вызывается для основных меню.

Для контекстных меню система проверяет всю цепочку респондента, начиная с представления.

Если вам нужно обновить команды главного меню в зависимости от их контекста:

  • Вы могли бы уйти buildMenu(with:) в UIApplicationDelegateдоговориться с делегатом, чтобы выяснить, когда и что изменилось, и позвонить UIMenu.main.setNeedsRebuild() когда это изменится, или
  • Вы можете определить частный метод buildMyMenu(with:) в вашей UIViewController подклассы, и организовать для buildMenu(with:) в UIApplicationDelegate позвонить или
  • Вы можете построить статическое меню в buildMenuи полагаться на свои переопределения canPerformAction(_:withSender:) а также validate(_:) включить или отключить или даже скрыть определенные команды, например, путем обновления attributes собственность в вашем validate(_:) переопределения.

Это предполагаемое поведение. Цитата из документов:

Поскольку меню могут существовать без иерархии окон или представлений, система обращается только кUIApplication а также UIApplicationDelegate для создания строки меню приложения.

На той же странице документации объясняется, как вы можете настраивать команды меню из контроллеров представления, а также есть отличный пример проекта, поэтому обязательно проверьте его.

Другие вопросы по тегам