Blog improve keyboard shorcuts speed Swift uikeycommand uiresponder Workflow

UIKeyCommand how-to add keyboard shortcuts & speed up your workflow

The UIKeyCommand class permits you to add keyboard shortcuts to your app. Though they could seem helpful for iPad only, there are causes to add this to your iPhone app as properly. They’re straightforward to set up they usually work within the simulator!

After I wrote Shortcuts essentials in Xcode to speed up your workflow and Helpful less recognized Xcode ideas to enhance your workflow that is one other great opportunity to vary your workflow and speed it up.

Getting used to this will speed up your improvement cycle by lots.

The right way to implement UIKeyCommand

Adding a UIKeyCommand to your customized responder class is straightforward. Each UIResponder class comes with a keyCommands collection variable. By overriding this property you possibly can provide the UIKeyCommands you need to enable. Key command sequences are generated only for units with an hooked up hardware keyboard.

override var keyCommands: [UIKeyCommand]?
return [UIKeyCommand(input: UIKeyCommand.inputEscape, modifierFlags: .shift, motion: #selector(dismiss), discoverabilityTitle: “Close modal view”)]

On this example, we’ve created a keyboard shortcut which can dismiss the view once you tap SHIFT + SPACE.

To make this key command truly work, we need to tell the responder chain that our view can grow to be the first responder.

override var canBecomeFirstResponder: Bool
return true

It’s good to know that the system is all the time checked first for the pressed key commands. The system will stop your shortcut from working if it has a shortcut assigned to the mixture. For different key instructions, the responder chain is used to seek out the first object that implements a key command for the pressed keys.

UIKeyCommand choices for set up

The UIKeyCommand lets you set up a mixture of keys. Its parameters work as follows:

That is the key that the consumer should press to make the key command work. An inventory of strings for particular keys permits you to catch input for:

  • Arrow up
  • Arrow down
  • Arrow reft
  • Arrow right
  • Escape

Modifier Flags
That is the place to define the important thing mixtures and with that, the keys the consumer also has to press. Examples are the command, choice and shift keys. For a full listing, you possibly can take a look at UIKeyModifierFlags.

This is merely the selector to execute once the important thing combination is pressed.

Discoverability title
Though this property is deprecated as of iOS 13, it’s required up until. This String value simply explains the aim of the key command to the consumer. A dialog displaying all keyboard shortcuts is accessible upon holding command on the iPad.

All out there keyboard shortcuts carried out with UIKeyCommand

Rushing up your workflow with key instructions

Now that you understand how to set up some key instructions it is time to speed up your workflow. By defining key instructions for your widespread views you’ll be able to simply navigate via your app without using the mouse. Getting used to this could speed up your improvement cycle by so much.

As testing within the simulator only permits shortcuts which aren’t already utilized by the simulator itself, you typically have to make key mixtures utilizing shift while command typically feels extra natural. By all the time using shift you make your keys straightforward accessible by just holding on shift in any respect time.

Including keyboard shortcuts to a UITabBarController

For a tab bar controller it is nice to have the likelihood to modify tabs using a keyboard shortcut. On this case, we’d like to modify utilizing SHIFT + Tab Index.

// MARK: – Keyboard Shortcuts
extension HomeTabBarController

/// Adds keyboard shortcuts for the tabs.
/// – Shift + Tab Index for the simulator
override var keyCommands: [UIKeyCommand]?
return tabBar.gadgets?.enumerated().map (index, item) -> UIKeyCommand in
return UIKeyCommand(input: “(index + 1)”, modifierFlags: .shift, action: #selector(selectTab), discoverabilityTitle: merchandise.title ?? “Tab (index + 1)”)

@objc personal func selectTab(sender: UIKeyCommand)
guard let input = sender.enter, let newIndex = Int(input), newIndex >= 1 && newIndex <= (tabBar.gadgets?.rely ?? zero) else return
selectedIndex = newIndex – 1

override var canBecomeFirstResponder: Bool
return true

Including a UIKeyCommand to a UINavigationController

Navigating back from a web page feels pure if we might use the again arrow identical to in many browsers. Even Xcode supplies us this feature through the use of CTRL + COMMAND + Again arrow.

Including this to our customized navigation controller class takes the next strains of code:

// MARK: – Keyboard Shortcuts
extension NavigationController

Adds keyboard shortcuts to navigate again in a navigation controller.
– Shift + left arrow on the simulator
override public var keyCommands: [UIKeyCommand]?
guard viewControllers.rely > 1 else return []
return [UIKeyCommand(enter: UIKeyCommand.inputLeftArrow, modifierFlags: .shift, motion: #selector(backCommand), discoverabilityTitle: “Back”)]

@objc personal func backCommand()
popViewController(animated: true)

override var canBecomeFirstResponder: Bool
return true

Controlling a UICollectionView utilizing keyboard shortcuts

From all these examples, that is the toughest one. We’d like a approach to hold monitor of the focussed cell and we additionally need to spotlight a cell upon focussing. This virtually seems like replicating the main target engine of tvOS.

Word: This code solely works for a UICollectionView, however is definitely convertible for a UITableView.

We’re first making a custom CollectionViewKeyCommandsController to make this code reusable for all our UICollectionView courses in our app.

This class takes reference to the focussed indexPath and modifications it accordingly based mostly on the info obtainable in the UICollectionView. The strategies are greatest to hook up with the next key mixtures:

  • SHIFT + Escape: Reset focus
  • SHIFT + Arrow down: Go to the subsequent cell
  • SHIFT + Arrow up: Go to the previous cell
  • SHIFT + Enter: Choose the presently focussed cell

The code for this seems to be as followed:

/// A commandscontroller to allow keyboard shortcuts in our app with a `UICollectionView`.
ultimate class CollectionViewKeyCommandsController
personal let collectionView: UICollectionView
personal var focussedIndexPath: IndexPath?
guard let focussedIndexPath = focussedIndexPath, let focussedCell = collectionView.cellForItem(at: focussedIndexPath) else return

UIView.animate(withDuration: zero.2, animations:
focussedCell.alpha = 0.5
, completion: _ in
UIView.animate(withDuration: zero.2, animations:
focussedCell.alpha = 1.0

init(collectionView: UICollectionView)
self.collectionView = collectionView

func escapeKeyTapped()
focussedIndexPath = nil

func enterKeyTapped()
guard let focussedIndexPath = focussedIndexPath else return
collectionView.delegate?.collectionView?(collectionView, didSelectItemAt: focussedIndexPath)

func nextKeyTapped()
guard let focussedIndexPath = focussedIndexPath else
self.focussedIndexPath = firstIndexPath

let numberOfItems = collectionView.numberOfItems(inSection: zero)
let focussedItem = focussedIndexPath.item

guard focussedItem != (numberOfItems – 1) else
self.focussedIndexPath = firstIndexPath

self.focussedIndexPath = IndexPath(item: focussedItem + 1, section: zero)

func previousKeyTapped()
guard let focussedIndexPath = focussedIndexPath else
self.focussedIndexPath = lastIndexPath

let focussedItem = focussedIndexPath.merchandise

guard focussedItem > zero else
self.focussedIndexPath = lastIndexPath

self.focussedIndexPath = IndexPath(item: focussedItem – 1, section: 0)

personal var lastIndexPath: IndexPath
return IndexPath(merchandise: collectionView.numberOfItems(inSection: 0) – 1, part: 0)

personal var firstIndexPath: IndexPath
return IndexPath(merchandise: 0, part: zero)

Now, we have to save an occasion of this class on our view controller which accommodates the collection view.

/// A controller to deal with all keyboard enter.
fileprivate lazy var collectionViewKeyCommandsController = CollectionViewKeyCommandsController(collectionView: collectionView)

After that, we will implement the code as earlier than to set up the important thing commands.

// MARK: – Keyboard Shortcuts
extension EditableCollectionViewController

override var keyCommands: [UIKeyCommand]?
return [
UIKeyCommand(enter: UIKeyCommand.inputEscape, modifierFlags: .shift, action: #selector(escapeKeyTapped), discoverabilityTitle: “Reset cell focus”),
UIKeyCommand(enter: UIKeyCommand.inputDownArrow, modifierFlags: .shift, action: #selector(nextKeyTapped), discoverabilityTitle: “Next item”),
UIKeyCommand(enter: UIKeyCommand.inputUpArrow, modifierFlags: .shift, action: #selector(previousKeyTapped), discoverabilityTitle: “Previous item”),
UIKeyCommand(enter: “r”, modifierFlags: .shift, action: #selector(selectKeyTapped), discoverabilityTitle: “Select item”),
UIKeyCommand(enter: UIKeyCommand.inputRightArrow, modifierFlags: .shift, action: #selector(selectKeyTapped), discoverabilityTitle: “Select item”)

override var canBecomeFirstResponder: Bool
return true

@objc func escapeKeyTapped()

@objc func selectKeyTapped()

@objc func nextKeyTapped()

@objc func previousKeyTapped()

Although this still leads to quite some duplicate code when you need to add help to multiple views, it’s the most effective method potential. Making an attempt to make CollectionViewKeyCommandsController conform to the UIResponder class didn’t work out as defined within the following chapter.

Making a customized UIResponder class

It turns out that it’s onerous to add a custom responder into the responder chain. It will’ve been as straightforward as passing in your customized occasion as the nextResponder by overriding the same named property. Nevertheless, the responder chain does not seem to like this and subsequently forces us to outline the key commands inside the views themselves.


The UIKeyCommand class permits us to create a win-win state of affairs. We’re adding keyboard help to our (future) iPad app and we also enable ourselves to navigate by means of our app on the simulator.

With the above code examples, it must be very straightforward to add primary shortcuts to your app. Obviously, you possibly can create some for yourself as properly based mostly on your needs. Some concepts:

  • Refresh utilizing SHIFT + R
  • Enable debug mode utilizing SHIFT + COMMAND + D

The chances are countless. Good luck!