Using the UIMenuController and Manipulating the Responder Chain

A detailed guide to handling events through UIMenuController with Swift

Alex Persian
May 20, 2019 · 4 min read
Image for post
Image for post

This piece focuses on the UIMenuController functionality and how it interacts with the UIResponder chain for handling events. It assumes that you are at least somewhat familiar with both, but if not please go read up a bit before continuing. You can also find an example project of this at the end.

Alright, now let’s get into the main portion of this. When a UIMenuController is displayed, it needs to have a firstResponder object. Usually, you just set the view that you want to display the menu above as the first responder and you’re good to go, but what if you want to show this menu above one view while another view is acting as the first responder? For example when a UITextView/UITextField is active and a user is typing something without having the keyboard dismiss. Well, there just happens to be a way to handle that, but you’ll have to do some manipulation of the responder chain to achieve it. Thankfully Apple has made it relatively straightforward to accomplish.

What we’re going to do is take two separate UIResponder chains, one representing the view the menu is presented on, let’s call that the “bubble view”, and one representing the text view that the user is typing into, and merge them. This will be within the context of a messaging feature, similar to Instagram’s chat. The goal will be to let the users type out messages while simultaneously being able to long-press on a message bubble to perform actions on it.

Here’s an example of our goal:

Image for post
Image for post

To start, we need to get a long-press gesture set up and attached, customize the UIMenuController singleton, and override canPerformAction in the presenting view to enable it to display the menu. I’m going to assume that’s ready to go from here on, but there are references at the bottom of this piece if you’d like more details.

We have the menu ready and running, but you might notice an issue. Whenever the menu pops up it causes the keyboard to hide.

Image for post
Image for post

To fix this, we’ll tweak the responder chain a bit. Essentially, we need the input text field to be the first responder, but for the view, we are tapping on to be the determiner of where the menu displays and what actions are shown. This is achieved by replacing the text field’s “next responder” object with the view we are tapping on.

First, we subclass UITextField and override nextResponder and provide our own override. This override will be the “bubble view” from above.

Along with this we also need to override the canPerformAction method on the UITextField so we can allow the overridden nextResponder to make the determination. This will be how we can allow the text field to “pretend” it can perform the UIMenuController’s actions later on.

The gist of what’s going on here is that if we have set our nextResponderOverride, i.e., we want the “bubble view” to handle this, we just return false no matter what. This causes the UIMenuController to check the text view's next responder which we’ve overridden to be our “bubble view”, and thus we’ve completed the responder chain swap.

Now the only thing left to do is set up our “bubble view” to handle the desired actions. We do that with the following:

Now, when you have the keyboard open and trigger your menu to display, it’ll display without taking over and hiding the keyboard! 🎉

Please drop a comment below with any questions or difficulties that come up when implementing this.

There will also be a follow-up post soon which will cover some of the edge case bugs that can show up when building this user interaction, such as the actions getting copied over when long-pressing into the text field. You can see this happen in the example below and within Instagram’s chat feature.

An example project of this in action is available here:

Stack Overflow reference answer:

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store