© Rob Whitaker 2020
R. WhitakerDeveloping Inclusive Mobile Appshttps://doi.org/10.1007/978-1-4842-5814-9_7

7. iOS Accessibility Features – General

Rob Whitaker1 
(1)
Derby, UK
 

Apple’s Human Interface Guidelines1 (often known as the HIG) are essential reading for anyone creating mobile apps for iOS – not just designers. The HIG sets out how Apple has worked to make UIKit flexible for you as an app developer but also clear and meaningful to your users.

The section on Accessibility2 is the starting point when considering how to introduce accessibility to your iOS app. The HIG gives you the best overview of using iOS’ built-in accessibility considerations. Keeping your apps consistent with this guide (not just the accessibility section) will help your users feel at home within your app, as many of the system patterns designed by Apple will carry over into your app and others. Plus, following this guide and ensuring a high level of accessibility mean your app is much more likely to get featured on the App Store. Both UIKit and SwiftUI provide powerful customization options to allow you to maintain accessibility while giving your app a distinctive look and feel.

People use Apple’s accessibility features , such as reduced transparency, VoiceOver, and increased text size, to personalize how they interact with their devices in ways that work for them. An accessible app supports such personalization by design and gives everyone a great user experience, regardless of their capabilities or how they use their devices.

—Apple Human Interface Guidelines: Accessibility

I asked Apple’s Accessibility team about the feedback they receive from their customers regarding the accessibility of third-party apps. They told me:

The two most common bits of feedback that we receive about the accessibility of third-party apps involve element labels and the order of navigation for VoiceOver. Additionally, color palette choices, Dark Mode support, and media captioning are all great practices.

—Apple Accessibility Team3

We cover accessibility labels in the section “Accessibility Protocol” of Chapter 6. Later in that chapter, we also include techniques for improving navigation order such as semantic views. For accessibility rules on choosing colors, see the Distinguishable guideline in Chapter 3. For guidance on including captions, see Chapter 10.

In this chapter, we’ll cover iOS system-wide accessibility features, why someone may enable them, and how having them enabled might affect your app. This is not an exhaustive list of accessibility settings; for more details on what’s available from an end-user perspective, see the accessibility section of Apple’s web site.4 Instead, this chapter focuses on accessibility settings that might change the way your app looks or works or settings that might require you to add code or make decisions to best support them.

In UIKit if you’re using the recommended system APIs – Dynamic Type, Accessibility Traits, etc., you’ll get many of these features for free. SwiftUI’s accessibility support is far better than UIKit, for reasons covered in the previous chapter, but will still require some customization. If you’re creating a non-native app through web views, or another cross-platform system, accessibility tools will often ape those of the system you’re compiling for. Ultimately as with anything cross-platform, features will vary and may be limited. While Apple will do as much as possible for you, some settings will require you to query iOS’ UIAccessibility framework for settings and make your own decisions about how to handle them.

From iOS 13 onward, the Accessibility menu is now a top-level menu in the system settings (Figure 7-1), grouped under four headings covering the class of impairment the technology is aimed to help with – general, vision, hearing, and physical and motor. iOS 12 and earlier, these features are found in the devices system settings, under General ➤ Accessibility.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig1_HTML.jpg
Figure 7-1

Accessibility settings in iOS 13 (right) found in the top level of device settings (left)

Each accessibility option in this menu provides a short description of what enabling this option does. Each option is instantly enabled and present system-wide once triggered. Guided Access requires an additional step to activate the feature once enabled.

Take some time to go through this menu; enabling each one, navigate through your app, and see how each option changes how your app looks and behaves. No setting is destructive and can be instantly disabled. Some settings, however, such as VoiceOver, do change how your device functions. So it’s worth reading a little about the features first, at least so you know how to disable them when you’re done. This menu is all about customizability, so you may find options you want to keep enabled on your personal device.

General Features

Apple breaks down its accessibility considerations into four categories – cognitive, motor, vision, and hearing (Figure 7-2). For this reason, I have broken the accessibility settings into four similar categories. Motor, vision, and hearing mirror Apple’s categories. While there aren’t specific settings to benefit those with cognitive impairments, many other settings will also help those falling into this category. In this first section, we’ll cover some of the general settings and features of iOS.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig2_HTML.jpg
Figure 7-2

Apple presenting its four categories of accessibility considerations at WWDC 2018

Accessibility Shortcut

I mention this first , as this will allow you a quick and easy way to enable many accessibility features on iOS. Therefore, it is the best way to test your apps work with many iOS accessibility tools. Having this simple feature enabled will encourage you to activate these features as a regular part of your development and testing workflows. Importantly, it’s also the simplest way to disable these features, which can save a lot of frustration once you’ve enabled a feature that changes how your device works.

Tip

Enable the Accessibility Shortcut before trying out anything else in this chapter.

Enable the accessibility shortcut in the accessibility settings on your device by going to Settings ➤ Accessibility ➤ Accessibility Shortcut. You’ll find Accessibility Shortcut as the last item on the list. I highly recommend enabling every item on the list, so you can try these out quickly when needed.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig3_HTML.jpg
Figure 7-3

Enable every option available in this list for easy access to that feature later

The options available on this menu are Assistive Touch, Classic Invert Colors, Smart Invert Colors, Color Filters, Magnifier, Reduce White Point, Switch Control, VoiceOver, Zoom, Guided Access, and Voice Control (Figure 7-3). However, the exact options may vary depending on the settings for your device. I recommend enabling each one of these on your testing devices; we’ll cover most of these features in more detail in this chapter.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig4_HTML.jpg
Figure 7-4

Accessibility shortcut activated after pressing the home or sleep button three times

You can then activate the accessibility shortcut when required by triple tapping the side button or home button on older devices. This presents a modal menu (Figure 7-4) where you can activate or deactivate the features you chose from the preceding list. I highly recommend keeping this shortcut enabled, as it doesn’t affect your regular use of the iPhone but gives you pain-free access to accessibility tools when you want to check something out.

Control Center

A second quick access way of toggling accessibility features, albeit a rather more limited one, is through Control Center . Swiping down from the top of the screen, or bottom-up on a device with a home button, will show a bunch of buttons providing quick access to common device controls (Figure 7-5). The controls displayed are customizable through your device’s Settings app. Follow Control Centre ➤ Customize Controls. Accessibility controls available here are Dark Mode, Guided Access, and Text Size. There is also an option to toggle the Accessibility Shortcut with the same options we chose in the setting we looked at above. Users with paired hearing aids can control them here too.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig5_HTML.jpg
Figure 7-5

Control Center with accessibility controls on the bottom row. L–R Text Size, Accessibility Shortcut, Dark Mode, and Guided Access

Guided Access

Guided Access allows a device to be locked only to the current app and disable certain app and system features. Guided Access makes the device into a stand-alone kiosk device and is often used in retail settings where you might not wish to give the public unrestricted access to a device. Guided Access is primarily designed, however, to be helpful for people with a range of different needs: Those with learning difficulties can easily get confused by new things or not fully understand the consequences of specific actions. People with motor issues can sometimes cause accidental input and are then unable to return the device to a state they can use. People who suffer from anxiety of attention-deficit disorders can become overwhelmed by too much stimulus. In all of these situations, restricting the options available is desirable.

Guided Access needs to be enabled in the device’s accessibility settings. Once enabled, it can be activated by using the accessibility shortcut of pressing the side or home button three times (Figure 7-6). Guided access is enabled per-app session and must be disabled to exit the app.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig6_HTML.jpg
Figure 7-6

Setting up Guided Access

You can detect if Guided Access is activated by checking isGuidedAccessEnabled and receive updates from guidedAccessStatusDidChangeNotification (Listing 7-1) when this setting is changed. In your app, you can use the status of this setting to decide whether to lock down individual features, such as settings, or destructive actions.
import UIKit
class MyViewController: UIViewController {
    var guidedAccessStatus: Bool {
        get{
            return UIAccessibility.isGuidedAccessEnabled
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(guidedAccessChanged), name: UIAccessibility.guidedAccessStatusDidChangeNotification, object: nil)
    }
    @objc
    func guidedAccessChanged() {
      // check guidedAccessStatus for current status.
      // Hide features as appropriate.
    }
}
Listing 7-1

Registering for notifications in guided access status

A better way to leverage this is to implement the UIGuidedAccessRestrictionDelegate on startup of your app. This delegate allows you to set custom actions that can be enabled or disabled on request when a customer enables guided access within your app. For example, you might add restrictions for “Settings” or “Delete Items.” This could then be configured by the person setting up guided access to enable the guided access user to customize settings to their preferences but not allow them to delete any items.

First, we need to create unique strings for each feature our users might want to disable. Creating these as an enum (Listing 7-2) allows us to keep this type safe and provide the additional data we need.
enum Restriction: String, CaseIterable {
    case settings = "com.myCompany.myApp.restriction.settings"
    case delete = "com.myCompany.myApp.restriction.delete"
}
Listing 7-2

Providing unique strings for Guided Access features

Next, we need human-readable strings for iOS to display to our customer – a short string used as a button label, then a longer descriptive string. Let’s extend our enum in listing 7-3 to associate those values with the unique string.
extension Restriction {
    var title: String {
        switch self {
        case .settings:
            return "Settings"
        case .delete:
            return "Delete"
        }
    }
    var detail: String {
        switch self {
        case .settings:
            return "Allow changing settings"
        case .delete:
            return "Allow permanent deletion of items"
        }
    }
}
Listing 7-3

Associating human-readable strings with our restrictions enum

Now we need to provide these strings to iOS in our app delegate by conforming to the UIGuidedAccessRestrictionDelegate (Listing 7-4). There are two protocol methods and one variable we need to conform to. The guidedAccessRestrictionIdentifiers variable is an array of unique strings for iOS and our app to identify features by. Then we have two functions, textForGuidedAccessRestriction and detailTextForGuidedAccessRestriction , where we provide our human-readable strings. To keep things neater in our app delegate, let’s do this in an extension.
extension AppDelegate: UIGuidedAccessRestrictionDelegate {
    var guidedAccessRestrictionIdentifiers: [String]? {
        return Restriction.allCases.map { $0.rawValue }
    }
    func textForGuidedAccessRestriction(withIdentifier restrictionIdentifier: String) -> String? {
        return Restriction(rawValue: restrictionIdentifier)?.title
    }
    func detailTextForGuidedAccessRestriction(withIdentifier restrictionIdentifier: String) -> String? {
        return Restriction(rawValue: restrictionIdentifier)?.detail
    }
}
Listing 7-4

Providing our Guided Access strings to iOS

Finally, we need to handle iOS’ callbacks when our user changes the Guided Access status of a feature (Listing 7-5). For this we need to conform to another delegate function in our extension, guidedAccessRestriction(withIdentifier restrictionIdentifier: didChange: ). This function provides us with a newRestrictionState enum value of either .allow or .deny.
    extension AppDelegate: UIGuidedAccessRestrictionDelegate {
...
func guidedAccessRestriction(withIdentifier restrictionIdentifier: String,
didChange newRestrictionState: UIAccessibility.GuidedAccessRestrictionState) {
        switch restrictionIdentifier {
        case Restriction.settings.rawValue:
            if newRestrictionState == .deny {
                // remove settings feature
            } else {
                // add settings feature
            }
        case Restriction.delete.rawValue:
            if newRestrictionState == .deny {
                // remove delete feature
            } else {
                // add delete feature
            }
        default:
            preconditionFailure()
        }
    }
}
Listing 7-5

Handling user changes in Guided Access feature status

Additionally, your app can query the guidedAccessRestrictionState(forIdentifier: String) function on the UIAccessibility API at any time to determine the status of a restriction (Listing 7-6). This can then be used to decide whether to deny an action or perhaps, preferably, hide an option altogether.
import UIKit
class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let deleteFeatureState = UIAccessibility.guidedAccessRestrictionState(forIdentifier: Restriction.delete.rawValue)
        switch deleteFeatureState {
        case .allow:
            // enable the delete feature
        case .deny:
            // disable the delete feature
        @unknown default:
            preconditionFailure()
        }
    }
}
Listing 7-6

Detecting the current status of a Guided Access restriction

Localization

Localization is built throughout iOS. While translating your app into different languages can be complex and nuanced, the coding to support this is not. You may feel your app doesn’t need localizing as your business is currently only available in one country, but this doesn’t reflect our global society. A significant number of people in any market will not have the market’s primary language as their first. Plus, removing hard-coded strings from your code is general good code health.

You’ll likely find your app is set up to begin localization even if you haven’t localized anything yet. But to check, go to your project’s settings, and scroll to the bottom (Figure 7-7). Here you’ll find a section for localizations. Ensure “Use Base Internationalization” is checked, and you’re good to go.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig7_HTML.jpg
Figure 7-7

Xcode Project’s Localization settings

From here you can press the + button to add a new language localization and begin the process of getting your app translated. To send your app’s strings to a translator, go to Xcode’s Editor menu, and choose Export for localizations. This will create all the files a translator will require. When you get your translation back, visit the same menu and select Import Localizations. Before you do this, however, there are a few changes you’ll need to make to your app.

Views

Any xib or storyboard file can be localized, and this means more than just strings.

Using autolayout is essential with localization, as it is with dynamic type. It is not possible to guarantee the visual length of your string will be for each localization. Many languages take up much more space than English. English’s 12-character localization becomes the 13-character Lokalisierung in German, while in simplified Chinese, it’s the 3-character 本土化. You can test this using pseudolanguage; we’ll cover this in Chapter 11.

Consider too that some languages, Arabic, for example, are written right to left. iOS will do a great job of flipping your UI for you, but this is based on autolayout constraints. So failure to make them resolve fully can have some strange effects. Finally, ensure your text’s alignments are correct. Only use left-aligned text if this is truly your intention for every experience. For most uses, you should use natural alignment. This presents text left to right in most languages but will switch to right to left when needed.

When creating a new localization by pressing the + button in Figure 5-3, Xcode presents you with a dialog asking what action you’d like to take with each view file in your project. You have two options – a new view file and a localized strings file. The localized strings file will be the preferred option for most uses. See the next section on strings for more on how this works.

The more heavy-duty option is to create a new view file. This duplicates the existing file but allows you to make modifications to the views, not limited to the text values. You can use these files to modify how your views work for languages that are much shorter or longer than your development language, or those languages that are written in a different direction. Be aware that any changes you make to one view file are not reflected in any of the others, meaning if you’re supporting five localizations, that’s five Interface Builder files you’re going to have to change. The good news is that different localizations can have different methods of localization. As an example, it’s possible to support four localizations with strings files and just one with a new interface Builder file.

When creating a new view file, these are not localized by default. If you decide to localize, select the file in the navigator, and open the file inspector. Press the Localize button (Figure 7-8) to generate localized versions of this view.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig8_HTML.jpg
Figure 7-8

Xcode File Inspector’s Localize button

Strings

Not all of your app’s strings will be embedded in storyboards. For these, you’ll need to create a Localizable.strings file. Visit File ➤ New ➤ File, and chose a Strings file. Call it Localizable.strings.

This file is a collection of key-value pairs for strings used in your app. The key can be in any string format you wish, but generally it’s best practice to keep the format consistent within your app. Try to make it evident from a glance this is a key, not a string. And try to clarify where the string is used and for what purpose. For these reasons, I prefer the format of using all caps naming the screen first, then the purpose of the string, separated by a period (Listing 7-7). End each line with a semicolon, even if you’re using Swift.
"DETAIL_PAGE.TITLE" = "Listing Detail";
Listing 7-7

A localized value of “Listing Detail” used as the title for the app’s detail page

To use these strings in code, use NSLocalizedString as in Listing 7-8. This takes your strings key as an argument and a comment. Xcode provides the comment to your translator to guide them on how best to translate the meaning. Be aware that if your localized string cannot be found, the key is the string displayed to your customer. For this reason, you can optionally pass a value property to provide a default.
        pageTitle.text = NSLocalizedString("DETAIL_PAGE.TITLE",
      value: "Listing Detail",
      comment: "Header for the listing page")
Listing 7-8

Setting the pageTitle UILabel’s text using a localized string in code

Localizing a Project
Let’s localize an existing project. If you haven’t already, clone the GitHub repo for this book. Open Exercise 7-1 in Xcode. If it’s not already selected, chose the project file from at the top of the project navigator. Then select the project in the editor pane.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig9_HTML.jpg
Figure 7-9

Finding the demo project’s localization settings

You’ll notice there are already two localizations (Figure 7-9). The base localization – the default; and English – my development language. Let’s go ahead and add another. I’m going to use Google Translate to get values in German; you can do the same to choose whichever language you wish.

Caution Never translate your apps using an automated service; always use a professional translation service.

Press the + button underneath Localizations and pick German (de) as seen in figure 7-10.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig10_HTML.jpg
Figure 7-10

Changing your scheme’s language

We’re going to use strings files, so on the next screen (Figure 7-11), make sure both the storyboard files have the Localizable Strings option selected.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig11_HTML.jpg
Figure 7-11

Select all the files you want to localize, and choose “Localizable Strings

In the project navigator on the left, a disclosure indicator has now appeared next to both files. Open the one next to Main.storyboard, and notice there are two children (Figure 7-12), the base localization storyboard and a new strings file marked German.
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig12_HTML.jpg
Figure 7-12

The project navigator showing our localized storyboards

First, let’s take a look at the storyboard file to see what strings we have. This app is for booking holidays to space (Figure 7-13), each detail page gives us information about the space destination we can visit, along with a photo. Most of the text that will appear in this view will vary depending on the listing, so we haven’t included them in this storyboard file. The only string we want to reuse across destinations is “Destination.”
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig13_HTML.jpg
Figure 7-13

Our holiday listing app showing the strings we need to localize

Open the new strings file. Xcode has generated a key-value pair for the only string we have in the storyboard. Here, replace the word Destination with “Ziel.”

The rest of our strings are set dynamically in code, so for those, we’ll need a localized strings file. Go to File ➤ New ➤ File, and choose a strings file. Name this Localizable.strings. We have three strings we need to move into this file from ViewController.swift. Add these with suitable keys, such as the example in listing 7-9.
"DETAIL_PAGE.MARS.HEADING" = "Mars";
Listing 7-9

An entry in a localizable strings file

Now we need to tell our view controller to use these new localized strings. Something like in listing 7-10.
     pageTitle?.text = NSLocalizedString("DETAIL_PAGE.MARS.HEADING",
     value: "Mars",
     comment: "Mars planet name")
Listing 7-10

Accessing a localized string in code

Be sure to follow the two steps above for the other two strings giving each its own identifier. Once you have done this, we need to create a German localization of our strings file. Select the file in the project navigator, and open the file inspector. Press the “Localize…” button (Figure 7-8). Xcode will then ask which localization the existing file belongs to. Select English and press Localize. Back in the file inspector, you’ll notice the Localize button has disappeared, and in its place is a list of your active localizations with a check next to English. Check German. A new file is created for you with the same content as the original. Here we can start to add our new German localized strings.

Mars in German is Mars. So let’s delete the key-value pair for the heading as we’ll just be using the default. Replace the subheading value with “Der Rote Planet,” and replace the description too. I’ll let you create your own translation here.

To run your app in German, without changing your device or simulator settings, edit your target’s scheme (Figure 7-14). Under Run ➤ Options, there is a dropdown for Application Language (Figure 7-15).
../images/486920_1_En_7_Chapter/486920_1_En_7_Fig14_HTML.jpg
Figure 7-14

Edit your app’s scheme to change the running language

../images/486920_1_En_7_Chapter/486920_1_En_7_Fig15_HTML.jpg
Figure 7-15

Change the application’s running language with the Application Language option

Change this to German and close the window. On next run, your app will display your new German translation.

Summary

  • Read Apple’s Human Interface Guidelines. It’s the last word in making your app feel at home on iOS for all of your users. Follow the advice Apple set out here, and you’re more likely to have your app featured on the App Store and less likely to get an app review rejection.

  • Enable the accessibility shortcut before continuing with the book, and keep it enabled even after you’ve finished reading. It gives you quick access to popular accessibility tools and will help with pain-free accessibility testing.

  • Preparing your app for localization is good practice as it removes hard-coded strings from your code and makes it easier to change them in future. If you do them decide to localize your app, a bunch of work is already done.

  • Even if your app is only available in one market you still stand to increase your market by localizing your app.

Over the next three chapters, we’ll dive a little deeper into the accessibility features Apple has created to benefit people with specific disabilities or requirements. The following chapter will cover the broadest range of features; vision considerations.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.187.121