Accessibility in Swift: Making iOS Apps Accessible for Everyone

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why Accessibility Is Not Just a Checkbox, But a Superpower for Your App

\n\n

Imagine: you've created a cool app. A beautiful interface, lightning-fast animations, perfect Swift code. You're proud of it. But suddenly it turns out that 15% of users can't use it. For them, the buttons are too small, the text blends into the background, and VoiceOver "reads" gibberish instead of the menu. Sound familiar?

\n\n

Accessibility is not about "mandatory requirements" or "doing it for the sake of a checkbox." It's about inclusivity, about care, and, importantly, about business. iOS has a powerful framework that allows you to adapt your app to the needs of people with visual, hearing, motor, and cognitive impairments. And Swift gives us all the tools to do this elegantly.

\n\n

In this article, we won't give boring lectures. We'll break down specific code examples that you can immediately implement in your project. Let's go!

\n\n

VoiceOver: How to "Teach" Your App to Describe Itself

\n\n

VoiceOver is a screen reader built into iOS. It "speaks" everything that happens on the screen: text, buttons, gestures. But if the developer hasn't prepared the interface, VoiceOver can turn into chaos. Let's fix that.

\n\n

Basic Setup: accessibilityLabel and accessibilityTraits

\n\n

The simplest way to help VoiceOver is to set labels and types for elements. For example, you have a button with a heart icon. Without a label, VoiceOver will just say "button," but with a label, it will say "Add to Favorites."

\n\n
let favoriteButton = UIButton(type: .system)\nfavoriteButton.setImage(UIImage(systemName: "heart"), for: .normal)\nfavoriteButton.accessibilityLabel = "Add to Favorites"\nfavoriteButton.accessibilityTraits = .button
\n\n

Note the accessibilityTraits. This is a hint for VoiceOver on how to interact with the element. For a button — .button, for an image — .image, for a heading — .header. Use .selected, .notEnabled, and others to accurately convey the state.

\n\n

Grouping Elements: How to Prevent VoiceOver from "Chattering" the User

\n\n

Sometimes it makes sense to combine several elements into one logical block. For example, a product card: image, name, price. If VoiceOver reads them separately, the user will get tired. The solution is UIAccessibilityElement or shouldGroupAccessibilityChildren.

\n\n
cardView.shouldGroupAccessibilityChildren = true\ncardView.accessibilityLabel = "Nike Air Sneakers, 12,990 rubles"\ncardView.accessibilityTraits = .button
\n\n

Now VoiceOver will read the entire card as one element. Brief, concise, clear.

\n\n

Custom Actions: When You Need More Than Just a "Tap"

\n\n

There are complex elements: sliders, switches, swipeable lists. For these, it's important to add custom actions. For example, for a cell with "Delete" and "Edit" functions:

\n\n
let deleteAction = UIAccessibilityCustomAction(\n    name: "Delete",\n    target: self,\n    selector: #selector(deleteItem)\n)\nlet editAction = UIAccessibilityCustomAction(\n    name: "Edit",\n    target: self,\n    selector: #selector(editItem)\n)\ncell.accessibilityCustomActions = [deleteAction, editAction]
\n\n

A VoiceOver user swipes down or up to select an action. This significantly improves the experience.

\n\n

Dynamic Type: Text That Adapts to Everyone

\n\n

People with low vision often increase the font size in iOS settings. If your app doesn't support Dynamic Type, the text will be cut off, overlap, or simply become unreadable. How to avoid this?

\n\n

Using Dynamic Font Styles

\n\n

Instead of a hardcoded UIFont.systemFont(ofSize: 16), use UIFont.preferredFont(forTextStyle: .body).

\n\n
label.font = UIFont.preferredFont(forText                

Blogs

Book Recommendations