![]() Rewritten in Swift 4. This sample contains examples of several common control elements with various implementations and code to make them accessible, including using the accessibility methods of NSControl subclasses and implementing accessibility protocols for custom elements. Signed-off-by: Liu Lantao <liulantao@gmail.com> |
||
---|---|---|
.. | ||
AccessibilityUIExamples | ||
AccessibilityUIExamples.xcodeproj | ||
Configuration | ||
.gitignore | ||
LICENSE.txt | ||
ReadMe.md |
ReadMe.md
Accessibility UI Examples
This sample shows how to implement accessibility for several common UI controls. The examples make the controls accessible by using accessibility properties, accessibility protocols, and the NSAccessibilityElement
class.
Overview
In macOS 10.10, the Accessibility API moved to a protocol-based approach, in contrast to the key-based API from macOS 10.9 and earlier.
The goals of this API are to:
- Simplify the implementation of accessibility
- Achieve better API parity with iOS
- Ensure compatibility with existing applications and code
Prior versions of the Accessibility API are deprecated, but can coexist alongside the new API. No changes are required for applications or accessibility clients that use prior versions of the Accessibility API. If both the new API and old API are implemented on the same class, the new API always takes precedence for that class. For cell-based controls, Accessibility API implementations should always be provided on the cell.
Accessibility Properties
Most accessibility attributes from 10.9 and earlier are now properties on the following AppKit classes:
NSApplication
NSWindow
NSView
NSDrawer
NSPopover
NSCell
To set an accessibility attribute value on an instance of one of these classes (or a subclass), simply assign the value to the property:
button.setAccessibilityLabel(NSLocalizedString("My label", comment: "label to use for this button"))
or override the getter in the subclass's implementation:
override func accessibilityLabel() -> String? {
return NSLocalizedString("Play", comment: "accessibility label of the Play button")
}
The NSAccessibility
contains the full list of accessibility properties.
Accessibility Protocols
The new Accessibility API includes accessibility protocols that define the required accessibility functions for many common accessibility elements. Conformance to an accessibility protocol is not required to use the new API, but conformance is recommended when making custom controls accessible. Conforming to an accessibility protocol displays a warning for each unimplemented required function and allows the accessibilityRole and isAccessibilityElement properties to be automatically inferred.
Standard AppKit controls conform to the appropriate accessibility protocol (for example, NSButton conforms to NSAccessibilityButton protocol, and NSSlider conforms to NSAccessibilitySlider protocol). Whenever possible, subclass from the appropriate AppKit control to leverage the built-in accessibility.
To add accessibility to a custom control:
- Conform to the appropriate protocol.
- Implement all the required functions. A warning appears for each unimplemented required function.
- Test using VoiceOver and Accessibility Inspector.
For example, to create a custom control that subclasses NSView and draws and behaves like a button:
class CustomButtonView: NSView {
If a custom control does not conform to an accessibility protocol, the accessibilityRole and isAccessibilityElement functions must also be implemented:
override func accessibilityRole() -> NSAccessibilityRole? {
return NSAccessibilityRole.button
}
override func isAccessibilityElement() -> Bool {
return true
}
NSAccessibilityElement
For objects that do not have a backing view (for example, a single view that draws several images, each of which should be individually accessible), create an instance of NSAccessibilityElement
for each object, and return an array of the instances from the accessibility parent's accessibilityChildren
function.
Convenience Methods
NSAccessibilityElement
has two convenience methods to simplify its use.
The accessibilityAddChildElement
function sets the specified element as one of the receiver’s accessibilityChildren
and also automatically sets the receiver as the specified element’s accessibilityParent. This behavior is useful when you create hierarchies of accessibility elements.
The accessibilityFrameInParentSpace
property allows the accessibility element to specify its frame relative to its accessibility parent, so that the accessibilityFrame
property value (given in screen coordinates) can be automatically recalculated whenever the element or any of its parents changes location.
The new Accessibility API includes two new convenience methods in AppKit/NSAccessibility.h
to simplify common accessibility tasks.
The NSAccessibilityFrameInView
convenience method converts frame
from parentView
's coordinate space to screen coordinate space. This is useful when you calculate an object's accessibilityFrame.
Likewise, the NSAccessibilityPointInView
convenience method converts point
from parentView
's coordinate space to screen coordinate space. This is useful when you calculate an object's accessibilityActivationPoint
.
Testing
AccessibilityInspector is a tool that displays all accessibility information for the element currently under the mouse, including the accessibility hierarchy, accessibility attributes, and accessibility actions. It also shows warnings for common accessibility problems such as a missing accessibility label. Accessibility Inspector can be launched from the Xcode > Developer Tools menu.
VoiceOver is the built-in screen reader on macOS. Enable it by choosing System Preferences > Accessibility > VoiceOver > Enable VoiceOver or by pressing Command-F5. For a tutorial on how to use VoiceOver, choose System Preferences > Accessibility > VoiceOver > Open VoiceOver Training.