Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2021 Accessibility & Inclusion

WWDC21 · 17 min · Accessibility & Inclusion

Support Full Keyboard Access in your iOS app

iPhone and iPad support numerous input modes for those with motor impairments, including touch interaction modification, Switch Control, and Full Keyboard Access. We’ll explore how people can interact with their devices solely through keyboard input, working through a real-life example to discover key APIs. We’ll also take you through some best practices for supporting motor accessibility when you integrate Full Keyboard Access in your apps.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 7 snippets

Accessibility custom actions swift · at 7:06 ↗
// Accessibility custom actions

let addAction = UIAccessibilityCustomAction(
    name: gameLocString("add"), image: UIImage(systemName: "plus.square")) { _ in
            self.addCard()
            return true
        }
        
let pinAction = UIAccessibilityCustomAction(
    name: gameLocString("pin"), image: UIImage(systemName: "pin.fill")) { _ in
            self.pinCard()
            return true
        }
        
cardView.accessibilityCustomActions = [addAction, pinAction]
Keyboard shortcuts: buildMenu swift · at 8:39 ↗
// Keyboard shortcuts

// In AppDelegate.swift
override func buildMenu(with builder: UIMenuBuilder) {
    super.buildMenu(with: builder)
    guard builder.system == .main else {
        return
    }
        
    let pinCommand = UIKeyCommand(title: gameLocString("pin"), image: UIImage(systemName:
        "pin.fill"), action:#selector(GameViewController.pinFocusedCard), input: "P",
        discoverabilityTitle:gameLocString("pin.card"))      
    let addCommand = UIKeyCommand(title: gameLocString("add"), image: UIImage(systemName: 
        "plus.square"), action: #selector(GameViewController.addFocusedCard), input: "A",
        discoverabilityTitle: gameLocString("add.card"))
    let identifier = UIMenu.Identifier("gameplay_menu")
    let menu = UIMenu.init(title: gameLocString("gameplay"), image:  UIImage(systemName
        "rectangle.grid.3x2"), identifier: identifier, children: [addCommand, pinCommand]);
        
    builder.insertSibling(menu, afterMenu: .view)
}
Keyboard shortcuts: canPerformAction swift · at 9:22 ↗
// Keyboard shortcuts

// In GameViewController.swift
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    if action == #selector(addFocusedCard) || action == #selector(pinFocusedCard) {
        return self.focusedCard != .none
    }
    return super.canPerformAction(action, withSender: sender)
}
Accessibility elements swift · at 10:35 ↗
itemView.isAccessibilityElement = true
itemView.accessibilityLabel = gameLocString(for: item)
Responding to user interaction swift · at 11:01 ↗
itemView.accessibilityRespondsToUserInteraction = false
Supporting accessible input swift · at 13:41 ↗
self.accessibilityUserInputLabels = [
    gameLocString("settings"),
    gameLocString("prefs"),
    gameLocString("preferences"),
    gameLocString("gear")];
Accessibility path swift · at 14:52 ↗
// Accessibility path

let rect = circleLevelButton.convert(levelButton.bounds, to: nil)

circleLevelButton.accessibilityPath = UIBezierPath(ovalIn: rect)


// If your button is in a scroll view, it’s generally better to
// override accessibilityPath and/or accessibilityFrame
extension CircleButton {
    open override var accessibilityPath: UIBezierPath? {
        get {
            let rect = self.convert(self.bounds, to: nil)
            return UIBezierPath(ovalIn: rect)
        }
        set {
            // no-op
        }
    }
}

Resources