Episode #483

Nested / Inline Menus

Series: Working with Context Menus

5 minutes
Published on March 30, 2021

This video is only available to subscribers. Get access to this video and 510 others.

In this episode we will see how to nest menus inside each other as well as dynamically choosing when to show a nested menus contents inline.

It might be interesting for us to have some pre-selected avatars to use. I've added a few avatars to the project and now I wanted to make a nested menu to display them for selection.

private func chooseExistingAvatarMenu() -> UIMenu {
    let avatars = ["ted", "gambit", "ficsit"]
    let avatarMenuItems = avatars.map { avatar -> UIAction in
        let image = UIImage(named: avatar)
        return UIAction(title: avatar.capitalized, image: image) { _ in
            self.avatarImageView.image = image
        }
    }

    return UIMenu(title: "Choose from existing...", image: nil, 
identifier: nil, options: [], children: avatarMenuItems)
}

Here we have a dynamic UIMenu we're building. How can we use it? Well it turns out that UIMenu conforms to UIMenuElement so we can use it as a child of another menu.

Let's go back to our main context menu and add this new menu as a child.

return UIMenu(title: "Avatar", children: [
  addAvatarAction, 
  self.chooseExistingAvatarMenu(),
  removeAvatarAction
])

showing nested menu item

If we tap "Choose from existing…" we'll see the submenu.

displaying nested menu

And choosing one of the avatars will update the image view. Neat!

Ted Lasso

In this case we have a short list of avatars to choose from. In this case it might be nice to show this menu inline. Let's change the options of the submenu to include .displayInline:

return UIMenu(title: "Choose from existing...", image: nil, identifier: nil,
    options: [.displayInline], children: avatarMenuItems)

Now we can see the nested menu line with the initial context menu:

displaying nested menu inline

This episode uses Swift 5.3, Xcode 12.4.