Implementing Context Menus in iOS 13 Using SwiftUI or UIKit
Learn how to show context menus in your iOS apps with this tutorial
With the release of iOS 13, context menus or contextual menus have become a convenient way to show the users additional functionality related to on-screen items.
Specifically, when you long-press (i.e., press and hold) an item, a context menu with some common actions will pop up.
One thing to note is that, unlike the previous Peek and Pop function that requires 3D Touch, context menus can be implemented on any devices running iOS 13 or later, giving more users access to this cool feature.
It has been widely used in various system apps, including Messages and Photos. Here’s an example of what a context menu looks like when a text message is long pressed.
This tutorial has three parts. First, I’ll review the principles for the implementation of context menus in your apps.
Second, I’ll show you the steps of how they are implemented using SwiftUI. Third, I’ll show you how they are implemented using UIKit.
Part 1. Implementation Principles
There is a set of official guidelines on how to implement the context menus from a user-interaction perspective. I’m summarizing the most important aspects here for your convenience.
If you decide to implement context menus in your apps, you may want to use them consistently in the app.
Lack of consistency will only lead to confusion on the user’s side, because they don’t know what will bring a context menu and what won’t. After a few failures, they will stop trying to see if your app has this feature even though it’s implemented in a few places in your app.
You don’t want to crowd the screen by providing tens of actions for the users. It’s not only overwhelming but also very inefficient to convey the available actions.
Thus, you always want to show the most commonly used actions, maybe no more than four actions, to the users. In addition, they should be ordered based on the likelihood of being used.
In other words, you should place the most-used actions at the top of the menu.
The menu should look simple. You don’t want to use long names for the actions. Keep them short, and the users shouldn’t have felt that they have spent time reading the actions. Just a quick glance should be sufficient for the users to know the available actions.
If the list of actions is long, there are a few options to make it simple. First, you can create a submenu that captures less-used actions.
Second, you can group the actions based on their intended behaviors and use separators to differentiate between groups.
Part 2. Implementation Using SwiftUI
Step 1. Project setup
For the current tutorial, we’ll just create a single-view app project in Xcode (File -> New -> Project -> Single View App, under the iOS tab).
This project will use Swift as the programming language and SwiftUI for the user interface design.
Step 2. Proof of concept
By default, Xcode will create a text label showing “Hello, World!” on the screen. We can simply add a context menu to this label by using the
.contextMenu modifier to the
Specifically, we’re adding a button with a
Text and an
Image. One thing to note is that SwiftUI manages the display of the
Even if you switch the order of
Text or embed one or both in an
HStack or even a
VStack, the context menu will be shown the same way.
In addition, even if you declare more than one
Text and one
Image, only the first one for each will be used.
Build the project and run it in a simulator. You’ll see something like the below.
Step 3. Multiple actions
Imagine that sometimes we have multiple actions for the context menu. In this scenario, we can arrange them based on their intended purposes so that related actions can be grouped together.
In the following example, we have a list of to-do tasks, and the user can change the color of the tag for the task.
Apparently, the colors belong to the same conceptual group, thus, they’re placed next to each other, while the remaining actions (i.e., copy and share) belong to the other group.
- As of now (Jan, 2020), SwiftUI handles the display of the text and the image. If you want to change the size, color, or other attributes, it won’t happen. I expect that with the improvement of SwiftUI, there should be more flexibility in terms of customizing the menu.
- If you do want to implement a more customized context menu like the one used in the Photos app, you need to implement it using UIKit, which I’ll show you in the next section.
Part 3. Implementation Using UIKit
Step 1. Project setup
For this part, we’ll still create a single-view app project in Xcode (File -> New -> Project -> Single View App, under the iOS tab). This project will use Swift as the programming language and Storyboard for the user interface design instead of using SwiftUI.
UITableView, and add it to the view controller. We create a struct called
Task, and create a list of tasks that are to be displayed in the table view.
Step 2. Show context menu
To show a context menu when a row is tapped, we will need to implement the following
In this method, we provide a
UIContextMenuConfiguration to the table view.
Specifically, we’ll pass three parameters:
identifier (the unique identifier for this configuration object),
previewProvider (the custom view controller to use when previewing your content), and
actionProvider (an action-based contextual menu).
For now, we set the
nil, which will use the default preview. In a later step, we’ll implement a custom view controller.
actionProvider, we’ll create a
UIMenu that has three menu items. After implementing this method, we can build our project and run it on a simulator.
Step 3. Show context menu with a submenu
Sometimes, we can create a submenu to group a set of actions with the same purpose.
In this example, we’ll create a submenu that allows the user to update the tag color of the task. These actions will be passed as the
children parameter in the
Now, the built project will look like the below.
Step 4. Show context menu with custom preview
To make the context menu more interesting, we can implement a custom preview.
To do that, we need to create a custom view controller that will be in charge of showing the preview. For the simplicity of this current tutorial, this view controller will just have a label showing the description of the task.
To show the preview as part of the context menu, you’ll just pass the view controller to the
previewProvider in the
UIContextMenuConfiguration as below.
To take it a step further, when the user taps the preview, we can bring up the preview to a full view, which requires the implementation of the following
Specifically, we’ll retrieve the
identifier from the configuration. As we set the task’s ID as the identifier, using the identifier, we can find out the task and show the preview view controller with the task of concern.
After implementing this method, we’ll see something like below.
- Context menus can be similarly implemented in a collection view. There is a great Medium tutorial article on this topic that I recommend.
- Context menus can be implemented to any
UIViewtype. To do that, you’ll need to create a
UIContextMenuInteractionobject, and add this interaction to the view using the
addInteraction(interaction: UIInteraction)method. To configure the context menu, we’ll just make the view controller conform to the
UIContextMenuInteractionDelegateprotocol. This protocol has the methods that can be similarly implemented as we just learned. You can refer to the official documentation for the methods of this protocol.
In this tutorial, we learned the principles regarding the implementation of the context menus. We also learned how we implement it using SwiftUI and UIKit.
Apparently, as of now, SwiftUI provides limited functionality with little customization, but the implementation just requires a few lines of code.
Nevertheless, if you want a more complex custom context menu, you definitely want to use UIKit, because it provides more interesting context menus with the possibility of implementing the custom submenu and preview.