Exploring Freelancing
Navigate freelancing as a developer; find clients, manage contracts, ensure timely payment, and learn from experiences!
I’ve been using SwiftUI for a while and recently worked on a watchOS app where I also tried to make it accessible.
When I first started on the app, I forgot to add accessibility labels for the system images, and I found it later while auditing it in the Accessibility Inspector.
SwiftUI doesn’t provide any initializer for Image
to have the label as a
parameter nor something to ignore it for accessibility purposes. So let’s create
one!
SF Symbols with Accessibility Label
I wasn’t sure what to name my custom view because AccessibilityImage
seemed
too long, while A11YImage
didn’t sound ideal. So I decided to term it
AYImage
instead.
The variables required for this view would be the name, accessibility label, and a boolean value if it would be hidden or not.
private var isHidden = false
private var systemName: String
private var label: Text = Text("")
For creating a labeled system symbol image, I require an initializer that takes the name of the symbol as well as the accessibility label associated with it.
/// Creates a labeled system symbol image that you can use as
/// content for controls, with the specified label for accessibility.
///
/// - Parameters:
/// - systemName: The name of the system symbol image.
/// - label: The label associated with the image used for accessibility.
public init(systemName: String, label: Text) {
self.systemName = systemName
self.label = label
}
I only need to have the name of the symbol as the parameter for the initializer. This helps to hide the image for better accessibility in a few cases.
/// Creates an unlabelled, decorative system symbol image which
/// is ignored for accessibility purposes.
///
/// - Parameters:
/// - systemName: The name of the system symbol image.
public init(systemName name: String) {
self.systemName = name
self.isHidden = true
}
The accessibility APIs got better, specific method names this year. To make sure that I’m supporting the older version as well, I’ll have to add a check for that and write the modifiers accordingly.
var body: some View {
if #available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) {
Image(systemName: systemName)
.accessibilityHidden(isHidden)
.accessibilityLabel(label)
} else {
Image(systemName: systemName)
.accessibility(hidden: isHidden)
.accessibility(label: label)
}
}
AYImage
As SF symbols are only available in Big Sur, I’ve to add a check for it as well.
Putting everything together, we’re ready to use our custom view!
@available(macOS 11.0, *)
struct AYImage: View {
private var isHidden = false
private var systemName: String
private var label: Text = Text("")
/// Creates a labeled system symbol image that you can use as
/// content for controls, with the specified label for accessibility.
///
/// - Parameters:
/// - systemName: The name of the system symbol image.
/// - label: The label associated with the image used for accessibility.
public init(systemName: String, label: Text) {
self.systemName = systemName
self.label = label
}
/// Creates an unlabelled, decorative system symbol image which
/// is ignored for accessibility purposes.
///
/// - Parameters:
/// - systemName: The name of the system symbol image.
public init(systemName name: String) {
self.systemName = name
self.isHidden = true
}
var body: some View {
if #available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) {
Image(systemName: systemName)
.accessibilityHidden(isHidden)
.accessibilityLabel(label)
} else {
Image(systemName: systemName)
.accessibility(hidden: isHidden)
.accessibility(label: label)
}
}
}
You can use it like this -
struct ContentView: View {
var body: some View {
AYImage(systemName: "gear", label: Text("Settings"))
AYImage(systemName: "square.and.arrow.up.on.square")
}
}
There are many instances where you may be using the gear
symbol for the
settings icon in the navigation bar and don’t want your user to hear gear
instead of a button.
Or worse, you don’t want the user to hear something absurd as “square.grid.3x1.folder.fill.badge.plus” for the “Add a folder” button.
I hope you enjoyed this code snippet and will create a better experience for your users!
Exploring Freelancing
Navigate freelancing as a developer; find clients, manage contracts, ensure timely payment, and learn from experiences!