# Accessibility up to 11! — Full content index > Machine-readable catalog for AI systems and coding agents. Summaries only; full markdown at each post's `.md` mirror URL. Generated: 2026-09-05T08:11:00Z Site: https://accessibilityupto11.com License: CC BY 4.0 — https://accessibilityupto11.com/content-license AI terms: https://accessibilityupto11.com/ai-tos.txt JSON index: https://accessibilityupto11.com/content-index.json ## About iOS, iPadOS, and visionOS accessibility development blog by Daniel Devesa Derksen-Staats. Practical tutorials, daily tips, and curated resources for UIKit and SwiftUI developers. ## Long-form blog posts - Learning to develop more accessible iOS games — I started my journey in iOS accessibility about 9 years ago, when I was working at the BBC. I even dared to give a talk about it in App Dev Con in 2018. Years later, I’m pretty sure that I was just…: https://accessibilityupto11.com/post/2026-02-22-01 Markdown: https://accessibilityupto11.com/post/2026-02-22-01.md - Advent of iOS Accessibility — Starting something new: The Advent of iOS Accessibility. Twenty-four days of exploring some of the most common accessibility issues I've encountered, how to identify them, and—most importantly—how to…: https://accessibilityupto11.com/post/2024-12-06-01 Markdown: https://accessibilityupto11.com/post/2024-12-06-01.md - Traits of a good accessible iOS app — You may know that you can configure a UI component with an accessibility label. The accessibility label is the name of the component. You can also configure an accessibility trait. The accessibility…: https://accessibilityupto11.com/post/2021-01-21-01 Markdown: https://accessibilityupto11.com/post/2021-01-21-01.md - Tips for testing your iOS app’s accessibility — The cycle for creating great accessible apps starts and ends with testing. Sure, it is always better to get feedback from users to create an experience that holds up to their expectations. But that’s…: https://accessibilityupto11.com/post/2020-08-11-01 Markdown: https://accessibilityupto11.com/post/2020-08-11-01.md - Improving your App’s Accessibility with iOS 13 — I know, iOS 13 has been with us for quite some time now, WWDC 2020 is just around the corner and we hope Apple will present again a ton of new accessibility features and improvements coming with iOS…: https://accessibilityupto11.com/post/2020-05-13-01 Markdown: https://accessibilityupto11.com/post/2020-05-13-01.md - Improving your App’s Accessibility with iOS 11 — Apple introduced iOS 11 at their World Wide Developer Conference (WWDC) in June 2017. WWDC is Apple’s showcase of new tools and developer APIs covering iOS, macOS, watchOS, and tvOS. In this post…: https://accessibilityupto11.com/post/2018-02-14-01 Markdown: https://accessibilityupto11.com/post/2018-02-14-01.md ## 365 Days iOS Accessibility — tag highlights - iOS (169 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/ios - VoiceOver (74 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/voiceover - Accessibility (42 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/accessibility - a11y (40 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/a11y - accessibilityLabel (38 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/accessibilitylabel - Dynamic Type (17 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/dynamic-type - SwiftUI (17 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/swiftui - accessibilityElement (15 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/accessibilityelement - UIKit (13 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/uikit - Voice Control (11 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/voice-control - Accessibility Inspector (9 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/accessibility-inspector - Full Keyboard Access (8 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/full-keyboard-access - HIG (8 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/hig - Switch Control (8 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/switch-control - accessibilityElements (7 posts): https://accessibilityupto11.com/365-days-ios-accessibility/tag/accessibilityelements ## 365 Days iOS Accessibility — all posts - Day 233: Multiple inputs for accessible spatial experiences — Abstracting your interface in a way that can offer multiple input and output mechanisms is key when developing software with an accessibility mindset. Apple has brought this to the next level in visionOS. Create accessible spatial experiences: https://accessibilityupto11.com/365-days-ios-accessibility/day-233 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-233.md - Day 232: UIKeyCommand shortcuts in UIKit — In UIKit you can create keyboard shortcuts by overriding the keyCommands for your view controller, which is an array of UIKeyCommand. A bit of a different approach to how you'd do it with SwiftUI.: https://accessibilityupto11.com/365-days-ios-accessibility/day-232 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-232.md - Day 230: keyboardShortcut modifier in SwiftUI — Adding keyboard shortcuts in your SwiftUI apps is extremely easy. Just use the .keyboardShortcut(_:) modifier. When pressing and holding the command key, the shortcut will appear in the shortcuts list.: https://accessibilityupto11.com/365-days-ios-accessibility/day-231 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-231.md - Day 230: Sydney Cocoaheads' spectacular GAAD event — Sydney Cocoaheads organized a pretty spectacular accessibility event for with an amazing lineup of speakers. Please check it out for a great crash course on accessibility with some of the best! https://m.youtube.com/watch?v=SKuWLHNHF28&t=2184s: https://accessibilityupto11.com/365-days-ios-accessibility/day-230 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-230.md - Day 229: accessibilityElement(children:) in SwiftUI — In SwiftUI there is a very useful modifier accessibilityElement(children:), that will do very different things depending on the AccessibilityChildBehavior passed as a parameter. There are three options: ignore (default), contain, and combine.: https://accessibilityupto11.com/365-days-ios-accessibility/day-229 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-229.md - Day 228: Set up your device for a11y testing — @azzoor has this great video with some advice on how to set up your device for testing accessibility and a ton of tips will get you testing effectively in no time. https://m.youtube.com/watch?v=Ca1H6wF348g&feature=youtu.be: https://accessibilityupto11.com/365-days-ios-accessibility/day-228 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-228.md - Day 227: accessibilitySortPriority for VoiceOver order — VoiceOver will traverse elements from left-right, and from top-bottom. If for any reason you need to change that order, in SwiftUI you can change the accessibility sort priority. A higher priority number in the container means it will go first.: https://accessibilityupto11.com/365-days-ios-accessibility/day-227 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-227.md - Day 226: Let users add alt text when sharing — If your app lets the user share images, consider implementing the possibility for them to add an alt text for the image, so it can be used as an accessibility label when consumed by other users. Twitter or Slack have nice flows for doing this.: https://accessibilityupto11.com/365-days-ios-accessibility/day-226 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-226.md - Day 225: Support both orientations when you can — Support both orientations, if possible. I know not even iOS itself does it, but it hasn't always been like that. You'll create a more robust UI that will be easier to port to iPadOS. And especially, don't force your users to rotate their devices.: https://accessibilityupto11.com/365-days-ios-accessibility/day-225 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-225.md - Day 224: We have one job: make our apps work — "We have one job, and that's to make our apps work. And if you are not implementing accessibility features, you are forgetting about making it work for a lot of people" @NovallSwift Couldn't have said it better! https://x.com/novallswift/status/1328387659744505856: https://accessibilityupto11.com/365-days-ios-accessibility/day-224 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-224.md - Day 223: Double-pinch quick actions on Watch — If your watch app has good VoiceOver support, chances are you'll also have good Assistive Touch support. But an improvement you can make is to implement a quick action (triggered with a double pinch) when there is a main action you can perform.: https://accessibilityupto11.com/365-days-ios-accessibility/day-223 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-223.md - Day 222: AssistiveTouch on Apple Watch — Assistive Touch for the Apple Watch works like magic. It lets you use your watch with gestures with the hand of the same arm you are wearing your watch on. No need to use your nose! If you don't have it on, is because you don't know about it.: https://accessibilityupto11.com/365-days-ios-accessibility/day-222 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-222.md - Day 221: Screen Curtain and VoiceOver shortcuts — It is useful to know these VoiceOver gestures to activate/deactivate Screen Curtain, pause/resume VoiceOver, easily simulate a long press for opening context menus, or quickly move the cursor to the screen's first or last elements.: https://accessibilityupto11.com/365-days-ios-accessibility/day-221 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-221.md - Day 220: Test manually with assistive technologies — Test manually. Familiarise yourself with different assistive technologies. I find it useful to start with VoiceOver but check out Voice Control, Full Keyboard Access, and others... Remove friction, configuring shortcuts can help. Merry Christmas!: https://accessibilityupto11.com/365-days-ios-accessibility/day-220 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-220.md - Day 219: Reflow layout for large text sizes — Sometimes your UI will just not scale for large text sizes. Simple changes, for large sizes, like disposing elements vertically instead of horizontally, reducing the number of columns, and allowing more lines of text, can do the trick most times.: https://accessibilityupto11.com/365-days-ios-accessibility/day-219 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-219.md - Day 218: Support accessibility Dynamic Type sizes — Make sure you support Dynamic Type up to the largest text size available. Take into account that there are five extra accessibility sizes available from the Accessibility Settings. It can make a huge difference for lots of users.: https://accessibilityupto11.com/365-days-ios-accessibility/day-218 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-218.md - Day 217: React to accessibility settings changes — There are a few accessibility settings you can check for, or get notifications in case these preferences change. This is especially important when developing custom components as they will mostly work with UIKit controls.: https://accessibilityupto11.com/365-days-ios-accessibility/day-217 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-217.md - Day 216: Respect Reduce Motion in animations — There is an option for the user to request an experience with Reduce Motion and we should honor it. If your app has animations, make sure to check if the user has this setting on. Here are three examples where Apple does a great job.: https://accessibilityupto11.com/365-days-ios-accessibility/day-216 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-216.md - Day 215: accessibilityUserInputLabels for Voice Control — Accessibility labels might not be the best input labels, used for example to find or interact with elements with Voice Control or Full Keyboard Access. In those cases, you can provide accessibility user input labels.: https://accessibilityupto11.com/365-days-ios-accessibility/day-215 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-215.md - Day 214: Set accessibility traits on custom controls — When building custom components, or if not relying on UIControl's attributes to configure state, it can be easy to forget to specify the right accessibility traits. These are indispensable for a good experience with VoiceOver, Switch Control...: https://accessibilityupto11.com/365-days-ios-accessibility/day-214 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-214.md - Day 213: Fix accessibility traversal order — Check for the traversal order of elements in your app. Sometimes, the default top-left to bottom-right order might not be the most logical one. Sometimes, you may consciously want to tweak the order. Some other times, grouping is the answer.: https://accessibilityupto11.com/365-days-ios-accessibility/day-213 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-213.md - Day 212: Combine color, haptics, and icons — A reminder that the more modes we use to convey important information, the more sure we'll be that it will be perceived by all our users. Consider a combination. of color, icons, messages, sound, haptics, animations, etc.: https://accessibilityupto11.com/365-days-ios-accessibility/day-212 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-212.md - Day 211: Keep touch targets at 44 points — Touch target sizes are recommended to be at least 44 x 44 points. Buttons in the navigation bar ( especially when not using nav bar button items), dismiss buttons, and custom toolbars, are use cases that tend to have smaller sizes.: https://accessibilityupto11.com/365-days-ios-accessibility/day-211 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-211.md - Day 210: Xcode and iOS color contrast tools — iOS and Xcode provide a wide variety of tools and options to deal with color contrast ratios. From system colors, that automatically support Increase Contrast, to high contrast color and asset variants, and even a built-in contrast calculator.: https://accessibilityupto11.com/365-days-ios-accessibility/day-210 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-210.md - Day 209: Accessibility for custom UI components — Sometimes, you may want to create a custom component, even if there is a similar one in UIKit because you want to style it in a way that the default one won't let you. That's fine, just take into account that you'll need to make it accessible.: https://accessibilityupto11.com/365-days-ios-accessibility/day-209 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-209.md - Day 208: Announce toasts and on-screen changes — Sometimes we may fail to convey to the user of things changing on the screen in a perceivable way. Toasts and similar should be announced. We may want to make clear that some content on the screen changed. Or we might want to update on progress.: https://accessibilityupto11.com/365-days-ios-accessibility/day-208 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-208.md - Day 207: Keep VoiceOver in modals with isModal — Have you ever seen VoiceOver randomly focusing on elements of the previous view when presenting a custom modal view? That can be fixed by letting the system know that the presented view is modal in terms of accessibility.: https://accessibilityupto11.com/365-days-ios-accessibility/day-207 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-207.md - Day 206: Common UISwitch accessibility mistakes — Toggles or UISwitches are often found separated from the label that precedes (and describes) them; with an unclear label; missing a value, trait, or hint; or even not being actionable at all.: https://accessibilityupto11.com/365-days-ios-accessibility/day-206 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-206.md - Day 205: Custom actions for hidden interactions — If you have interactions that are hidden or require complex gestures to be performed or that may conflict with VoiceOver, you need to provide alternative ways of executing these actions. Custom actions can help a lot of times, but not always.: https://accessibilityupto11.com/365-days-ios-accessibility/day-205 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-205.md - Day 204: isAccessibilityElement and nested controls — If a view has isAccessibilityElement to true, assistive tech won't look for any of its subviews. That means that if there are any buttons inside, they won't be accessible. You can add custom actions to that element though.: https://accessibilityupto11.com/365-days-ios-accessibility/day-204 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-204.md - Day 203: Group elements to ease VoiceOver navigation — Grouping elements when it makes sense can make a huge impact on easing navigation with some assistive technologies like VoiceOver, Switch Control, or Full Keyboard Access. It also helps on reducing redundancy.: https://accessibilityupto11.com/365-days-ios-accessibility/day-203 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-203.md - Day 202: The button trait for tappable views — With regular buttons from UIKit or SwiftUI, you are all set. With complex views, headings, or table/collection view cells that, when selected, bring the user somewhere else in the app or perform an action, you'll have to add the button trait.: https://accessibilityupto11.com/365-days-ios-accessibility/day-202 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-202.md - Day 201: Alt text and decorative images — Images should either be decorative or have a proper accessibility label or alt text that describes them. If they're decorative you can make it so they get skipped by assistive tech so it doesn't get in the way of the experience.: https://accessibilityupto11.com/365-days-ios-accessibility/day-201 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-201.md - Day 200: Don't miss visual cues in accessibility labels — There are details conveying important information that are shown visually with little icons, badges, progress bars, and similar cues that can be missed when they are not added as part of the accessibility label or accessibility value of a UI component.: https://accessibilityupto11.com/365-days-ios-accessibility/day-200 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-200.md - Day 199: Mark headings with the header trait — Anything representing a heading in the app should have the header trait. It allows for a faster way of exploring a screen and jumping to the part of the app you are interested in. Screens should also start with a header.: https://accessibilityupto11.com/365-days-ios-accessibility/day-199 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-199.md - Day 198: Writing better accessibility labels — Some recommendations for improving your accessibility labels: don't add the element type, avoid redundancy and verbosity, localize... @MobileA11y has an excellent blog post on it: https://mobilea11y.com/blog/writing-great-labels/ @jordyn2493 has a great video too: https://developer.apple.com/videos/play/wwdc2019/254/: https://accessibilityupto11.com/365-days-ios-accessibility/day-198 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-198.md - Day 197: Unlabelled elements: the issue I see most often — One of the accessibility issues I see more often in iOS apps, believe it or not, is unlabelled elements. This happens especially for buttons with an icon but no title. In those cases, you need to configure an accessibility label manually.: https://accessibilityupto11.com/365-days-ios-accessibility/day-197 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-197.md - Day 196: The VoiceOver Rotor and power gestures — Once you learn some basic gestures with VoiceOver, it is very important to master he Rotor. It is very useful to also know some more power user gestures like the Magic Tap or the Escape gesture.: https://accessibilityupto11.com/365-days-ios-accessibility/day-196 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-196.md - Day 195: VoiceOver on iPhone without a Home button — When using VoiceOver on a device without a home button it can first be confusing how you can do a few things, including going to Home from an app, or opening the App Switcher, Control Center, or Notifications. Here's a quick guide for you.: https://accessibilityupto11.com/365-days-ios-accessibility/day-195 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-195.md - Day 194: Essential VoiceOver gestures to learn first — Let's quickly remember a few of VoiceOver's most important gestures that will let you do some of the most basic actions including selection, interacting, navigating, and scrolling. And Apple has a great video: https://m.youtube.com/watch?v=qDm7GiKra28&feature=youtu.be: https://accessibilityupto11.com/365-days-ios-accessibility/day-194 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-194.md - Day 193: System semantic colors and contrast — The most straightforward way for making sure your colors work well in all appearances (dark, light, increase contrast, and all the combinations) is to use the provided system colors. Check the background and label semantic colors too. All the info in the Color section of Apple’s Human Interface Guidelines: https://developer.apple.com/design/human-interface-guidelines/color: https://accessibilityupto11.com/365-days-ios-accessibility/day-193 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-193.md - Day 192: Increase Contrast for colors defined in code — If you don't use Color Sets in your Asset Catalog, and you define your color palette in code, you can still check if the user has Increase Contrast enabled to offer a slightly different color that improves the contrast ratio even more. Day 192 (2/2). You can check if the darker system colors is enabled: https://developer.apple.com/documentation/uikit/uiaccessibility/isdarkersystemcolorsenabled Listen to a notification in case this setting changes: https://developer.apple.com/documentation/uikit/uiaccessibility/darkersystemcolorsstatusdidchangenotification And also check if the accessibility contrast is high in your trait collection: https://developer.apple.com/documentation/uikit/uitraitcollection/accessibilitycontrast: https://accessibilityupto11.com/365-days-ios-accessibility/day-192 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-192.md - Day 191: Stress-test UI with Double-length Pseudolanguage — I recommend running your app with Double-length Pseudolanguage. It is a great way to stress-testing your app and see how adaptive it is and if your UI will hold to other languages that might be a bit more verbose or even with larger text sizes.: https://accessibilityupto11.com/365-days-ios-accessibility/day-191 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-191.md - Day 190: Be My Eyes: sighted help when you need it — @BeMyEyes, founded by @hjwiberg, enables people who are blind and low vision to identify objects by pairing them with volunteers from around the world using their camera. Winner of an Apple Design Award 2021 for Social Impact.: https://accessibilityupto11.com/365-days-ios-accessibility/day-190 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-190.md - Day 189: Test Increase Contrast beyond color tweaks — Sometimes it won't be enough to make colors darker or lighter for Increase Contrast. As always, it is important to do some testing. The same colors might be used with different backgrounds or text colors and the contrast could actually get worse.: https://accessibilityupto11.com/365-days-ios-accessibility/day-189 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-189.md - Day 188: High Contrast image variants in Assets — You can enable the possibility of providing assets for different appearances including light/dark modes and high contrast. As we've seen, that's valid for colors, but you can do the same for images too! https://x.com/dadederk/status/1594724075590619138?s=20&t=XJrlJiGSCTR9sJC7XPZPjA: https://accessibilityupto11.com/365-days-ios-accessibility/day-188 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-188.md - Day 187: High Contrast variants in Color Sets — If you use Color Sets in the Assets Catalog to define your color palette, make sure you enable variants for the Any, Light and Dark appearances and also High Contrast. You'll be able to define variations of the color that have better contrast.: https://accessibilityupto11.com/365-days-ios-accessibility/day-187 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-187.md - Day 186: What Zoom testing reveals in your UI — I used to think of Zoom as an accessibility feature that didn't need support from developers. But actually, testing with Zoom might unveil some issues and bad practices. Watch out for buttons that change something far away on the screen. Using a snackbar is usually not a good idea. Especially if it lets you do/undo something. Because they're ephemeral, they're difficult to spot and/or reach with Zoom, VoiceOver, Switch, Keyboard... Confirming a destructive action with a dialog might be better.: https://accessibilityupto11.com/365-days-ios-accessibility/day-186 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-186.md - Day 185: Zoom gestures on iOS — Zoom lets the user magnify the screen if the user needs to zoom in a region to be able to see any details a bit closer. It is useful to know the gestures that let you zoom in, back out, move around the screen, adjust zoom level or show its menu.: https://accessibilityupto11.com/365-days-ios-accessibility/day-185 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-185.md - Day 184: Bonus content from 36 Seconds — While you are at @shelly's "36 Seconds That Changed Everything", I would definitely also check out the Bonus Content. Including the full interview with @marcoarment. "Awareness is the biggest problem here." https://www.36seconds.org/behind-the-scenes/ "Cause iOS 7 was so inaccessible in so many ways (...) it started getting under developers’ radars this section of settings, called accessibility, that changes the way my app looks or works and I need to make sure that it doesn’t break under those settings.” "There’s so much variation out there. We no longer have just one size phone, we no longer have just one font size. It is easier for us as developers not to fall into bad assumptions of how I see it is how everyone is going to see it.” "The good thing about VoiceOver is that the accessibility framework is pretty well built-in the standard controls. For a given app you can fix any VoiceOver problems it has in one day or less. Even if it is a complex app. Even if it has a lot of custom controls." "What developers now do, if they care, is they treat that (accessibility issues) as if it was any other design flaw. If any other screen in your app broke visually or functionally you’d consider that a bug and you would try to fix it in the next update.” "I think the more that we can do as a developer community to talk about these features even existing, and these problems existing, and to tell people how easy it is to fix. That is the best any of us can do to help. Awareness is the biggest problem here.": https://accessibilityupto11.com/365-days-ios-accessibility/day-184 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-184.md - Day 183: 36 seconds that changed everything — WWDC 2009's keynote, Phil Schiller spoke for 36 seconds, about how the iPhone was, two years later, finally accessible. @shelly tells this amazing story in her audio-documentary "36 Seconds That Changed Everything" https://www.36seconds.org/2019/06/19/36-seconds-transcript/ "Apple didn’t develop VoiceOver for Mac out of the goodness of their hearts. They developed VoiceOver for Mac because if they didn’t they were going to be in serious trouble with their key market, which was education," @JonathanMosen says. "They did that thinking a third party would write the screen reader for Mac OS 10, and then when really nobody picked up that mantle to write the screen reader as a third party, Apple stepped in and developed VoiceOver," @jamesdempsey says. "I borrowed a friend’s phone. It was confirmed. The screen was too small, the background too bright, the text too tiny. For the first time in 20 years, Apple had built a product I couldn’t use. I’m fairly sure I cried about that." @shelly Four minutes before the two-hour mark, in the midst of a long list of new apps to be included on the iPhone 3GS, @pschiller switched slides, revealing the iPhone Accessibility settings screen. “VoiceOver is on the iPhone. They did it.” "I bought myself an iPhone at the same time as other people. I didn’t have to wait for a new version of the software, an update to be made, or someone sighted to help me. I could start up VoiceOver and it just worked great." @SteveOfMaine: https://accessibilityupto11.com/365-days-ios-accessibility/day-183 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-183.md - Day 182: ScreenReader: learn VoiceOver gestures playfully — @JanJaapdeGroot presented the ScreenReader app for An app to help anyone learn VoiceOver's gestures in a very creative and playful way.: https://accessibilityupto11.com/365-days-ios-accessibility/day-182 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-182.md - Day 181: Preview Dynamic Type with SwiftUI variants — There are a ton of things to love about SwiftUI. But one of my favorites it's got to be the possibility of previewing Variants: the possibility of seeing your UI in dark/light modes, all dynamic type sizes, and orientations, side-by-side.: https://accessibilityupto11.com/365-days-ios-accessibility/day-181 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-181.md - Day 180: SwiftUI's Accessibility Inspector panel — If you are using SwiftUI to build your apps, there is a fairly basic but very useful Accessibility Inspector built right there in the Inspectors Panel, on the right side of Xcode.: https://accessibilityupto11.com/365-days-ios-accessibility/day-180 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-180.md - Day 179: Watch VoiceOver events in Inspector — The Accessibility Inspector has a Notifications log that you can find in Window, in its top menu, and then Show Notifications. It shows accessibility-related notifications like layout changed, screen changed, or announcements... I learned about this feature from the Accessibility Inspector in this article by @basthomas. A very recommended read to learn all about the Verifying VoiceOver with the Accessibility Inspector. https://www.basbroek.nl/verifying-voiceover: https://accessibilityupto11.com/365-days-ios-accessibility/day-179 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-179.md - Day 178: Inspect other apps with Accessibility Inspector — The Accessibility Inspector can be used with your device. It is actually quite interesting to check what other apps (or iOS) configure, for some of the basic accessibility attributes (label, value, traits, hint...), in their UI components.: https://accessibilityupto11.com/365-days-ios-accessibility/day-178 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-178.md - Day 177: Preview accessibility before you run — In addition to being able to test some accessibility options in the simulator using Environment Overrides. You can even preview some of these options before even running the app in the simulator with this Accessibility panel in Interface Builder.: https://accessibilityupto11.com/365-days-ios-accessibility/day-177 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-177.md - Day 176: Set accessibility traits in Interface Builder — If you use Interface Builder to build your app’s layout, there are some basic accessibility attributes that can be configured from there. They can be found in the Identity Inspector in the right-side panel in Xcode.: https://accessibilityupto11.com/365-days-ios-accessibility/day-176 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-176.md - Day 175: Input labels help keyboard users too — Accessibility Labels are not just for VoiceOver, and Accessibility User Input Labels are not just for Voice Control. The latter will also help Full Keyboard Access users to find elements on the screen by different names. Good API design!: https://accessibilityupto11.com/365-days-ios-accessibility/day-175 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-175.md - Day 174: Spotlight: Jordi Bruin and Navi — Meet @jordibruin developer of Navi (and other great apps) and organizer of @swiftuiseries (with an accessibility category). Navi is sadly not available anymore but it was worth an Apple Design Awards nomination. It added subtitles to FaceTime!: https://accessibilityupto11.com/365-days-ios-accessibility/day-174 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-174.md - Day 173: Braille Scanner reads braille with ML — @azzoor is the developer of the Braille Scanner It uses computer vision to locate the page and Machine Learning to match Braille to letters. You can see English letters above the braille, convert them to speech, copy and paste it... so cool!: https://accessibilityupto11.com/365-days-ios-accessibility/day-173 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-173.md - Day 172: Accessibility is caring, not just APIs — It is not just about applying accessibility APIs, but about caring, and thinking of features that can make your app more accessible and inclusive to everyone. Twitter's alt-text feature is a great example. Thanks, @TwitterA11y! You'll be missed.: https://accessibilityupto11.com/365-days-ios-accessibility/day-172 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-172.md - Day 171: Find weak labels with Show names — When using Voice Control, say: "Show names". You'll see all the accessibility labels for interactive elements overlaid on the screen. It will help you identify labels that can be improved, or actually missing. Labels are not just for VoiceOver.: https://accessibilityupto11.com/365-days-ios-accessibility/day-171 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-171.md - Day 170: Try Full Keyboard Access in Simulator — Full Keyboard Access can be tested in the simulator! So convenient! You can enable it from Accessibility's settings in the simulator. And from there, you can navigate your app by just using your computer's keyboard.: https://accessibilityupto11.com/365-days-ios-accessibility/day-170 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-170.md - Day 169: Bump text size fast in Simulator — The fastest way for testing Dynamic Type while developing, and to quickly see how your app's UI flows, is by using the "option + cmd + plus/minus" to increase/decrease the text size in your simulator.: https://accessibilityupto11.com/365-days-ios-accessibility/day-169 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-169.md - Day 168: Override accessibility settings while debugging — There is an Environment Overrides panel in the toolbar on top of Xcode's Debug Area. It allows you to select some of the most common accessibility options and Dynamic Type sizes, like in the Accessibility Inspector, plus select dark/light mode.: https://accessibilityupto11.com/365-days-ios-accessibility/day-168 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-168.md - Day 167: Calculate color contrast in Inspector — There is a Color Contrast Calculator conveniently built into the Accessibility Inspector. Find it in Window, in the top menu. Select two colors for text and background and check if it passes for all text sizes or just some of the largest ones.: https://accessibilityupto11.com/365-days-ios-accessibility/day-167 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-167.md - Day 166: Flip accessibility settings in Inspector — The Accessibility Inspector lets you configure on or off some of the most common accessibility options so you can conveniently observe how your app adopts these options in the simulator or device. You can also quickly select different text sizes.: https://accessibilityupto11.com/365-days-ios-accessibility/day-166 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-166.md - Day 165: Run accessibility audits in the simulator — The Accessibility Inspector let’s you run an audit of the current screen in your simulator or device. It can find some basic issues like color contrast issues, touch target sizes that are too small, etc. It can also provide with fix suggestions.: https://accessibilityupto11.com/365-days-ios-accessibility/day-165 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-165.md - Day 164: Inspect labels, traits, and actions — With the Accessibility Inspector you can check the value for the most common accessibility attributes for individual elements, do some basic navigation, and even perform actions if the component is adjustable or if it has custom actions.: https://accessibilityupto11.com/365-days-ios-accessibility/day-164 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-164.md - Day 163: Xcode's Accessibility Inspector, explained — Xcode has a built-in tool to help you develop more accessible apps, the Accessibility Inspector. You can find it in the Developer Tool set in the Xcode menu. It has three main functionalities: inspect, audit and settings.: https://accessibilityupto11.com/365-days-ios-accessibility/day-163 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-163.md - Day 162: Turn on VoiceOver with Siri — A quick way for turning on, or off, VoiceOver is by using Siri. Say something like: "Hey, Siri! Turn on VoiceOver", and you'll find yourself using VoiceOver in no time. You can also do the same with other technologies like Voice Control.: https://accessibilityupto11.com/365-days-ios-accessibility/day-162 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-162.md - Day 161: Show what VoiceOver says on screen — One thing I find very useful when testing (or doing demos!) is to have VoiceOver's caption panel enabled. It shows constantly at the bottom of the screen and you can see exactly what VoiceOver is saying.: https://accessibilityupto11.com/365-days-ios-accessibility/day-161 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-161.md - Day 160: Turn on larger accessibility text sizes — Reminder to enable Larger Accessibility Sizes, so you can pick from one of the five extra accessibility sizes when configuring text sizes. You can do it from Settings, Accessibility, Display & Text Size, and Larger Text.: https://accessibilityupto11.com/365-days-ios-accessibility/day-160 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-160.md - Day 159: Change Dynamic Type per app quickly — Text Size is one of my favorite Control Centre controls. It lets you quickly change the Dynamic Type size, of the whole system. But also, you can now specify a different setting per app. Also, check out Dark Mode, Magnifier, Sound Recognition...: https://accessibilityupto11.com/365-days-ios-accessibility/day-159 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-159.md - Day 158: Put accessibility testing in Control Centre — You can add your Accessibility Shortcuts to Control Centre too. One more quick access point and one more reminder to get you testing often and quickly. How to enable Accessibility shortcuts: https://x.com/dadederk/status/1583519154165800960?s=61&t=_fK9Muzu2MyFEeJLVQZcJg: https://accessibilityupto11.com/365-days-ios-accessibility/day-158 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-158.md - Day 157: Triple-click into accessibility shortcuts — Manual testing is crucial. And therefore, reducing friction to let you start your testing process can be a huge help. Selecting some accessibility shortcuts will do that, putting most of iOS' accessibility features at a triple-click of a button.: https://accessibilityupto11.com/365-days-ios-accessibility/day-157 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-157.md - Day 156: Test VoiceOver behind Screen Curtain — This is my favorite way of testing VoiceOver. Pick a flow in your app. Turn VoiceOver on. Triple tap with three fingers on the screen to enable Screen Curtain. The screen goes off but you can still navigate your device with VoiceOver.: https://accessibilityupto11.com/365-days-ios-accessibility/day-156 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-156.md - Day 155: Celebrate success with haptic feedback — UINotificationFeedbackGenerator has a “success” feedback type. Consider using it when a task was performed successfully together with any other visuals or sound. The use of multiple modes just makes it easier for everyone to understand your app.: https://accessibilityupto11.com/365-days-ios-accessibility/day-155 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-155.md - Day 154: Use haptics when tasks fail — You can indicate that an error occurred using haptic feedback. It can be useful for long-running tasks that fail, like page loads or downloads. But you can also use it as errors occur like Twitter does when reaching the character limit.: https://accessibilityupto11.com/365-days-ios-accessibility/day-154 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-154.md - Day 153: More takeaways from a11yTO — Second day of @a11yTO! And again, lots of talks with a ton of practical information. So here's a thread with some of my highlights. And very proud that @spotifydesign was one of the sponsors!: https://accessibilityupto11.com/365-days-ios-accessibility/day-153 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-153.md - Day 152: Takeaways from a11yTO for iOS developers — Today and tomorrow I'll be learning at @a11yTO. There haven't been any talks about iOS specifically. But I thought I'd share in a thread some of today's learnings that I think still apply when developing accessible apps for iOS. @a11yMel on continuous accessibility for quality at scale and reducing risks. Measure progress, but focus on people. When a measure becomes a target, it ceases to be a good measure. Accessibility is good for business but great for users. @annaecook talked about annotating designs for accessibility. Loved that she thinks of it as a communication and learning tool that can help divide the gap between design and development. I'd give it a go and see if it works for your team. Ann Mayer talked about writing accessible content. Technically compliant doesn't mean accessible. It is about being clear. The use of plain language principles, for example, is something that benefits everyone. @DavidOfYork has shown how deceptive patterns harm people with anxiety and panic disorders. If you spot any of these in your app, call them out and raise awareness. We all suffer eventually from anxiety, accessibility is for everyone. Michaela Peterhansl's practical guide for accessibility: Bring a11y to your daily work; you are not the only one responsible; ask questions; and find the people you can team-up with. "Don't forget: You can't do it alone", "Change is slow". @DDame on how to get stakeholders to invest in accessibility through storytelling and data: I may have a disability, but my money doesn't. Do we want to exclude users? Offer them a bad experience? No. We will all be disabled one day. Niki Ramesh gave useful tips to help you engage with a great a11y champions network. "Accessibility is not one person's job". Start informal/small, scale over time. Find representation across teams. Community, education, and recognition. @ShellELittle talked about hiring accessible designers but touched on some points that apply to anyone working on accessibility. It can't be done by one person or you risk burnout. Jennifer Payne on the importance of user research for building accessible products. Listen to users with disabilities. "Unless we consciously include, we unconsciously exclude". @svinkle showed how important it is to shift accessibility to the left (early in the process) so you get more voices involved through ideation, prototyping, and design. And remember to prioritize progress over perfection.: https://accessibilityupto11.com/365-days-ios-accessibility/day-152 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-152.md - Day 151: Reinforce warnings with haptic feedback — Haptics helps you signal important information in multiple modes. For example, you can use a UINotificationFeedbackGenerator to reinforce some "warning" feedback. Twitter uses this when you are running out of characters when composing a tweet.: https://accessibilityupto11.com/365-days-ios-accessibility/day-151 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-151.md - Day 150: Books that level up your accessibility game — Today I have a question for you: which books have helped you level up your accessibility game? I'll start: *Developing Inclusive Mobile Apps* by Rob Whitaker (@RobW). It is not just iOS—you also learn about Android, inclusive design, and WCAG.: https://accessibilityupto11.com/365-days-ios-accessibility/day-150 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-150.md - Day 149: Keep media readable with Smart Invert — Classic Invert reverses the colors of the display. But there's also Smart Invert. To support it, for avoiding images and media from being inverted, you just have to set accessibilityIgnoresInvertColors to true, for these elements. A quick win!: https://accessibilityupto11.com/365-days-ios-accessibility/day-149 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-149.md - Day 148: Help Voice Control guess button names — Have you used Voice Control? It feels like magic! But it would be cool if you could have an easier time guessing the name of a button without the “Show names” command. We can do that! Meet accessibilityUserInputLabels. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilityuserinputlabels: https://accessibilityupto11.com/365-days-ios-accessibility/day-148 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-148.md - Day 147: Make icons work with Bold Text — Your iconography should support Bold Text too. One way of doing it is by creating custom symbols (and specifying weights for it) to work with them as you would with regular SF Symbols. How Creating custom symbols: https://developer.apple.com/videos/play/wwdc2021/10250/: https://accessibilityupto11.com/365-days-ios-accessibility/day-147 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-147.md - Day 146: Ship bolder fonts when Bold Text is on — If the user has Bold Text enabled, it will just work if you are using fonts based on text styles. If you have your own styles, or you are using a non-system font, you'll need to provide the bolder version of the font when the setting is on.: https://accessibilityupto11.com/365-days-ios-accessibility/day-146 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-146.md - Day 145: Detect Bold Text with UIAccessibility — In iOS' Settings you can specify your preference to use bold text. This can be checked in code in a couple ways: 1. isBoldTextEnabled in UIAccessibility: https://developer.apple.com/documentation/uikit/uiaccessibility/isboldtextenabled 2. legibilityWeight from UITraitCollection: https://developer.apple.com/documentation/uikit/uitraitcollection/legibilityweight: https://accessibilityupto11.com/365-days-ios-accessibility/day-145 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-145.md - Day 144: Tone down animations for Reduce Motion — Some animations can be a lot for some people. They may opt to reduce motion in Settings. You can know by checking isReduceMotionEnabled. You’ll immediately see that the system’s animations are much more subtle. The weather app is a great example.: https://accessibilityupto11.com/365-days-ios-accessibility/day-144 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-144.md - Day 143: Adapt UI when Reduce Transparency is on — Check isReduceTransparencyEnabled to lower transparency. A great example is Spotlight. Not only transparency is removed but it keeps the main color of the background, it feels personalized and contextual but reduces noise and improves contrast.: https://accessibilityupto11.com/365-days-ios-accessibility/day-143 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-143.md - Day 142: Listen to articles with Speak Screen — Today I want to share something I use a lot. You can convert any article into a “podcast” by enabling Speak Screen in Accessibility Settings, switching to Safari’s Reader Mode and swiping down with two fingers from the top of the screen. I think it is a good example of how if we all knew more about how to use the assistive tech available in iOS, we would find ourselves using more of them, more often, exemplifying quite well that accessibility benefits everyone.: https://accessibilityupto11.com/365-days-ios-accessibility/day-142 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-142.md - Day 141: Don't rely on color alone — You should convey important information in multiple modes, not just color. If you are still required to do so, at the very least you should complement that info with other modes, like symbols, if the user requested differentiation without color.: https://accessibilityupto11.com/365-days-ios-accessibility/day-141 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-141.md - Day 140: React when accessibility settings change — All the accessibility capabilities you can check for, have counterpart notification names you can observe in case the user changes its preferences while using your app. https://x.com/dadederk/status/1577435144129892352: https://accessibilityupto11.com/365-days-ios-accessibility/day-140 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-140.md - Day 139: Respect iOS accessibility settings in code — There are a ton of customisation options in the accessibility settings in iOS. When doing things the Apple way, this options should, in most cases, just work for you. If not, you can find flags to check for all these options in UIAccessibility.: https://accessibilityupto11.com/365-days-ios-accessibility/day-139 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-139.md - Day 138: Watch for content size category changes — You can add an observer to listen for changes in the content size category, in case it is more convenient than overriding traitCollectionDidChange(_:).: https://accessibilityupto11.com/365-days-ios-accessibility/day-138 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-138.md - Day 137: Follow Accessible Mobile Apps Weekly — If you want to keep yourself up to date with what’s going on, or what has been published lately, on how to develop more accessible mobile apps, make sure you subscribe to Accessible Mobile Apps Weekly by @RobinKanatzar from @accessible_apps.: https://accessibilityupto11.com/365-days-ios-accessibility/day-137 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-137.md - Day 136: Raise label line limits for large text — Consider setting a higher number of lines in your labels for large content size categories. Even to 0 (it means unlimited). That way you ensure the user will have access to the same amount of content regardless of the text size configured.: https://accessibilityupto11.com/365-days-ios-accessibility/day-136 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-136.md - Day 135: Catch missing image labels with SwiftLint — If you use SwiftLint in your SwiftUI project, there is a rule, by @rerycole34, for making sure that your images have either an accessibility label or are hidden for assistive tech because they might be decorative. Rule: https://realm.github.io/SwiftLint/accessibility_label_for_image.html: https://accessibilityupto11.com/365-days-ios-accessibility/day-135 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-135.md - Day 134: Handle perform escape in SwiftUI — You can pass the .escape AccessibilityActionKind to the accessibilityAction(_:_:) modifier, to implement the perform escape gesture in SwiftUI. A reminder of how perform escape works: https://x.com/dadederk/status/1549066893377830913?s=20&t=Aog7ojR4E4eG4M3hd-cn3w: https://accessibilityupto11.com/365-days-ios-accessibility/day-134 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-134.md - Day 133: Great NSSpain accessibility talks to watch — @NSSpain has a great history of having amazing accessibility talks in their schedule! “Accessibility in the Real World”, by @Sommer: https://vimeo.com/235317172 “How to build an app for everyone”, by @NovallSwift: https://vimeo.com/362163043 The super fun "Choose your own SwiftUI adventure - 3 Accessibility", by @twostraws and @PinkerStraws: https://vimeo.com/481768105 And, of course, this year's great "Bas: My Accessibility Story", by @basthomas: https://vimeo.com/751176747: https://accessibilityupto11.com/365-days-ios-accessibility/day-133 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-133.md - Day 132: My NSSpain talk recording is online — A very special one for me today! The recording of my talk is now available! If you've been following , you'll find lots of the slides familiar. I would love to hear what you think about it! https://x.com/NSSpain/status/1574801556775620614?s=20&t=Aog7ojR4E4eG4M3hd-cn3w: https://accessibilityupto11.com/365-days-ios-accessibility/day-132 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-132.md - Day 131: Handle magic tap in SwiftUI — Looking at how to implement the magic tap in SwiftUI? There is an accessibilityAction(_:_:) with an action kind parameter, you can pass .magicTap, and a closure to handle that action. A reminder of what the magic tap is: https://x.com/dadederk/status/1548791545800888322?s=20&t=ZakzzXNfLk0-2kpYqD5v3A: https://accessibilityupto11.com/365-days-ios-accessibility/day-131 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-131.md - Day 130: Scale custom UI with UIFontMetrics — For other UI elements that could also benefit from being scaled when using Dynamic Type, you can use UIFontMetrics's scaledValue(for:). Some good examples are progress bar components, which tend to be quite slim. https://developer.apple.com/documentation/uikit/uifontmetrics/scaledvalue(for:): https://accessibilityupto11.com/365-days-ios-accessibility/day-130 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-130.md - Day 129: Support Dynamic Type in WKWebView CSS — If you have any web views in your app (Terms and Conditions and Privacy Policy, I'm looking at you), you can also support Dynamic Type for them. You can set an Apple system font with the same styles available for native development in your CSS.: https://accessibilityupto11.com/365-days-ios-accessibility/day-129 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-129.md - Day 128: Keep large content icons crisp with PDFs — When configuring a largeContentImage or adjustsImageSizeForAccessibilityContentSizeCategory, it is important to use a pdf asset and preserve the vector data so the icons are crisp at any size.: https://accessibilityupto11.com/365-days-ios-accessibility/day-128 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-128.md - Day 127: Configure Large Content Viewer titles and images — When implementing the large content viewer, UIKit components will usually have a large content title and image configured for you. But if you are developing a custom component, or you want to add info to a native component, you can do so.: https://accessibilityupto11.com/365-days-ios-accessibility/day-127 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-127.md - Day 126: Add Large Content Viewer to custom bars — You should really try to support Dynamic Type. If you can’t for some reason, and you want to fall back to the Large Content Viewer, you can do so. I’d limit it to “sticky” bars. Maybe you have a custom tab bar, navigation bar, or similar? Check the UILargeContentViewerItem protocol. Most UIKit components conform to it already. You'll just need to set showsLargeContentViewer to true and add a UILargeContentViewerInteraction to your component. https://developer.apple.com/documentation/uikit/uilargecontentvieweritem: https://accessibilityupto11.com/365-days-ios-accessibility/day-126 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-126.md - Day 125: Tap and hold bar items at large text sizes — You may have noticed that navigation/tool/tab bars don't scale with large Dynamic Type sizes. It would take too much space from the screen leaving very little real estate for the actual content. A tap and hold will show the Large Content Viewer.: https://accessibilityupto11.com/365-days-ios-accessibility/day-125 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-125.md - Day 124: Let UIImageView scale for accessibility sizes — Images can automatically scale for accessibility content size categories, by setting the adjustsImageSizeForAccessibilityContentSizeCategory property to true, for any UIImageView you'd like to get its size adjusted. https://developer.apple.com/documentation/uikit/uiaccessibilitycontentsizecategoryimageadjusting/adjustsimagesizeforaccessibilitycontentsizecategory: https://accessibilityupto11.com/365-days-ios-accessibility/day-124 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-124.md - Day 123: Space label baselines for Dynamic Type — What is the ideal distance between labels? It depends on styles for both of them and the dynamic type size, right? You wouldn't want to have the same distance for small and large text sizes. We can configure a standard distance between baselines.: https://accessibilityupto11.com/365-days-ios-accessibility/day-123 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-123.md - Day 122: Find ideal label width with readableContentGuide — Ever wondered what the ideal width is for labels so the text is readable? Well, it depends. But readableContentGuide has you covered. You can configure the optimal width independently of Dynamic Type size or Size Classes. https://developer.apple.com/documentation/uikit/uiview/readablecontentguide: https://accessibilityupto11.com/365-days-ios-accessibility/day-122 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-122.md - Day 121: Switch Auto Layout constraints for large text — An alternative layout for large font sizes can be provided with Auto Layout by having three sets of constraints (common, default constraints, and alternative constraints) and activate/deactivate them depending on the content size category.: https://accessibilityupto11.com/365-days-ios-accessibility/day-121 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-121.md - Day 120: Use fewer columns with large Dynamic Type — If you are displaying something in two or more columns, you may want to change that to as little as one column when using some of the largest Dynamic Type settings to keep the text readable.: https://accessibilityupto11.com/365-days-ios-accessibility/day-120 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-120.md - Day 119: Flip stack axis for large Dynamic Type — One of my favourite Dynamic Type tricks is to use Stack Views and flip the axis from horizontal to vertical given a certain content-size-category threshold. So effortless and it works so well in so many scenarios.: https://accessibilityupto11.com/365-days-ios-accessibility/day-119 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-119.md - Day 118: React to any content size category — You don't have to offer an alternative layout just for the accessibility category. You can actually compare content size categories. So you could tweak the UI already for anything equal to or larger than .extraExtraLarge, for example.: https://accessibilityupto11.com/365-days-ios-accessibility/day-118 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-118.md - Day 117: Adapt layouts for accessibility text sizes — Sometimes, with large font sizes, there's no other way around it but to offer an alternative layout. Small tweaks are often enough. Otherwise, the text will be barely readable. Larger text shouldn't mean less content or a worse experience. One thing you can do is to check if the preferred content size category of a view is an accessibility category. And, in that case, move things around to make room for the text, offer more lines of text, etc. https://developer.apple.com/documentation/uikit/uicontentsizecategory/isaccessibilitycategory: https://accessibilityupto11.com/365-days-ios-accessibility/day-117 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-117.md - Day 116: Scale custom fonts with UIFontMetrics — It is possible to use custom fonts and for them to still work great with Dynamic Type. You need to define the default size and use UIFontMetrics to get the scaled font for each one of the styles you'd like to use. https://developer.apple.com/documentation/uikit/uifontmetrics/scaledfont(for:): https://accessibilityupto11.com/365-days-ios-accessibility/day-116 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-116.md - Day 115: Enable adjustsFontForContentSizeCategory — I wish the adjustsFontForContentSizeCategory was true by default. Instead, you need to configure it that way so elements adjust their font size as the content size category (dynamic type) changes when a preferred font is used for a given style.: https://accessibilityupto11.com/365-days-ios-accessibility/day-115 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-115.md - Day 114: Dynamic Type sizes don't scale linearly — When working with Dynamic Type, I find it useful to remember that sizes for the different text styles won't scale linearly, nor will they do proportionally between them. For larger dynamic type sizes, styles will come closer together in size.: https://accessibilityupto11.com/365-days-ios-accessibility/day-114 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-114.md - Day 113: Support Dynamic Type with text styles — Dynamic Type is a feature that lets a user change the font size (smaller or larger) of the whole system or a particular app. To support it, choose a preferred font based on one of the 11 supported text styles: Large title, heading, body...: https://accessibilityupto11.com/365-days-ios-accessibility/day-113 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-113.md - Day 112: Map custom views with accessibilityRepresentation — With accessibilityRepresentation(representation:), you can create a custom component and it can be perceived by assistive technologies as the view you pass as representation. No need to manually configure accessibility attributes. It is one of the most interesting additions to SwiftUI to help you develop accessible UI components. If your custom component behaves similarly to a native one, this is the way to go. https://developer.apple.com/documentation/swiftui/view/accessibilityrepresentation(representation:): https://accessibilityupto11.com/365-days-ios-accessibility/day-112 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-112.md - Day 111: Use disabled instead of notEnabled in SwiftUI — In SwiftUI you won't find the .notEnabled accessibility trait. Instead, you can just configure a view as such with .disabled(true), and pass false to enable it. VoiceOver will announce it as "dimmed". https://developer.apple.com/documentation/swiftui/view/disabled(_:): https://accessibilityupto11.com/365-days-ios-accessibility/day-111 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-111.md - Day 110: Manage accessibility traits in SwiftUI — As with UIKit, in SwiftUI you can also add/remove a11y traits. But because of its declarative nature, you'll have to approach it in a slightly different way. A little nuance, but something that made me scratch my UIKit head when learning SwitUI.: https://accessibilityupto11.com/365-days-ios-accessibility/day-110 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-110.md - Day 109: SwiftUI contain mirrors semanticGroup — The equivalent of using a .semanticGroup accessibilityContainerType in UIKit, would be to use the .accessibilityElement(children: ) modifier with the .contain option in SwiftUI. Here's a refresher with some use-cases: https://x.com/dadederk/status/1558790851496742914: https://accessibilityupto11.com/365-days-ios-accessibility/day-109 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-109.md - Day 108: Build adjustable controls in SwiftUI — In UIKit, to create an adjustable component we need to add the adjustable trait and override both accessibilityIncrement() and accessibilityDecrement(). In SwiftUI, everything you need is bundled in the accessibilityAdjustableAction(_:) modifier.: https://accessibilityupto11.com/365-days-ios-accessibility/day-108 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-108.md - Day 107: Fix combined SwiftUI accessibility labels — Grouping elements with .accessibility(children: .combine) doesn't always generate the best accessibility label. Comma-separating labels might sometimes not be ideal. But you can improve it by tweaking the labels/grouping of its children first.: https://accessibilityupto11.com/365-days-ios-accessibility/day-107 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-107.md - Day 106: Prefer combine before accessibilityElement ignore — Apple asks us to consider the combine behavior, before using ignore, for .accessibilityElement(children: ). And for good reason, if combine works, and later on you decide to change the UI, the accessibility attributes will be updated for you.: https://accessibilityupto11.com/365-days-ios-accessibility/day-106 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-106.md - Day 105: SwiftUI accessibilityElement like UIKit grouping — The .accessibilityElement(children: ) modifier with the .ignore argument does a similar thing to set the container view to be an accessibility element in UIKit. It is the default argument, so you can just say .accessibilityElement(). Because of this, you'll need to use other modifiers to make it accessible and manually configure an accessibility label and value, traits... when necessary. https://developer.apple.com/documentation/swiftui/view/accessibilityelement(children:) https://developer.apple.com/documentation/swiftui/accessibilitychildbehavior/ignore: https://accessibilityupto11.com/365-days-ios-accessibility/day-105 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-105.md - Day 104: Combine elements in SwiftUI accessibility — Grouping elements in SwiftUI is extremely easy! You can use the .accessibility(children: .combine) modifier. And that's it! It merges properties. For example, generating an accessibility label by joining the children's ones, separated by commas.: https://accessibilityupto11.com/365-days-ios-accessibility/day-104 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-104.md - Day 103: Tailor VoiceOver with accessibilityCustomContent — If you want to know everything about how to "Tailor the VoiceOver experience in your data-rich apps" with the Accessibility Custom Content API, there is a WWDC21 session. https://developer.apple.com/videos/play/wwdc2021/10121/ When implementing accessibilityCustomContent, for any supplementary information, it returns an array that VoiceOver will announce in that given order. The value of the AXCustomContent first, then the label. Users can configure in VoiceOver's verbosity settings if it should say that there's more content available, or play a sound hinting that there is, or simply do nothing. So it should really be optional content as users might miss it.: https://accessibilityupto11.com/365-days-ios-accessibility/day-103 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-103.md - Day 102: Set AXCustomContent importance for VoiceOver — When creating AXCustomContent objects for accessibilityCustomContent, you can specify the importance of the data. If it is high, it will always be presented by VoiceOver. You could potentially ask the user if that data is of importance to them.: https://accessibilityupto11.com/365-days-ios-accessibility/day-102 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-102.md - Day 101: Mark optional data with AXCustomContent — Too much data can overwhelm users. Very little is an incomplete experience. It is hard to find a balance on verbosity and the users may have different preferences. To help with this issue, the AXCustomContent APIs let you mark data as optional.: https://accessibilityupto11.com/365-days-ios-accessibility/day-101 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-101.md - Day 100: Who invented VoiceOver? — We've spoken a lot about VoiceOver in the past 100 days. But who invented VoiceOver? The answer to this question and other fascinating stories from Mike Shebanek are in these amazing episodes of *13 Letters*: - Who invented VoiceOver? - Accessibility should be free > "Apple had been a worldwide leader in this. Late 70s, early 80s. The company was starting to fade, and so accessibility disappeared. Probably for about 10 years. 2004, and my manager says: hey, what are we doing? Nothing. We have nothing." > "Alan Brightman going to John Scully, the CEO, and Steve Jobs before Steve was ousted from the company, saying, 'If you're going to build a computer for the rest of us, then you should build a computer for all of us.'" > "Not just deliver a screen reader but change the whole idea. And that's when I thought, we need to build this in. We need to make this free. It needs to be everywhere. It needs to be there before you know you need it.": https://accessibilityupto11.com/365-days-ios-accessibility/day-100 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-100.md - Day 99: Group chart data into accessibility chunks — When making charts accessible, sometimes you may have just too many data points for the user to have to go one by one through all of them. In those cases, you can create accessibility elements that represent meaningful chunks of the graph.: https://accessibilityupto11.com/365-days-ios-accessibility/day-099 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-099.md - Day 98: Accessible chart color and contrast tips — Some good practices when it comes to charts and data visualizations: use high contrast colors, avoid problematic pairings (red-green, blue-yellow), use symbols as well as colors...: https://accessibilityupto11.com/365-days-ios-accessibility/day-098 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-098.md - Day 97: Customize taps with accessibilityActivationPoint — When something is focused with VoiceOver, if you double tap on the screen, it will be like interacting with the centre of the focused element. If you need to change that, you can customise the accessibilityActivationPoint. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilityactivationpoint: https://accessibilityupto11.com/365-days-ios-accessibility/day-097 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-097.md - Day 96: Audio Graphs trends, outliers, and stats — The Audio Graphs API has some very nice features aside from being able to consume the graph as audio. You can give it a summary and it will also provide your users with trends, correlations, outliers... and statistics like min and max or the mean.: https://accessibilityupto11.com/365-days-ios-accessibility/day-096 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-096.md - Day 95: Explore charts with Audio Graphs (AXChart) — Love this feature! Yahoo released the possibility to explore charts with audio, in the finance app, when using screen readers in 2019. You can do now something very similar since iOS 15. https://coolblindtech.com/yahoo-finance-app-makes-charts-accessible-to-blind-and-partially-sighted-users/ You can move your finger in the x-axes, and it will play a sound with a different pitch depending on the data in the y-axes, making it easier to identify trends in the graphs. You need to conform to the AXChart protocol by implementing the accessibilityChartDescriptor property. Documentation: https://developer.apple.com/documentation/accessibility/audio-graphs WWDC21 session: https://developer.apple.com/videos/play/wwdc2021/10122/: https://accessibilityupto11.com/365-days-ios-accessibility/day-095 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-095.md - Day 94: Make charts accessible with UIAccessibilityElement — Creating UIAccessibilityElements, combined with a semanticGroup accessibilityContainerType, can also help you make components as complex as charts accessible. Example from "Bring Accessibility to Charts" WWDC21: https://developer.apple.com/videos/play/wwdc2021/10122/: https://accessibilityupto11.com/365-days-ios-accessibility/day-094 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-094.md - Day 93: Group distant views with UIAccessibilityElement — Sometimes you can create your own accessibility elements from scratch to group elements too. Perhaps because they're not contained in the same superview. You can combine these elements' frames and provide a suitable accessibility label.: https://accessibilityupto11.com/365-days-ios-accessibility/day-093 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-093.md - Day 92: Create UIAccessibilityElement for custom drawing — You can create your own accessibility elements from scratch. One use-case for doing that is when you do some custom drawing instead of building your UI using or relying on UIKit components. A circular progress bar, could be an example.: https://accessibilityupto11.com/365-days-ios-accessibility/day-092 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-092.md - Day 91: Respond when VoiceOver turns on or off — You can check if VoiceOver is running but you can also get a notification to act in case that changes, while the user is using your app. As seen before, you rarely want to do significant changes in the experience when VoiceOver is on. But this use-case presented by @djembe from @NetflixEng at @appbuilders_ch is an excellent example of inclusive design. When VoiceOver is on, they bump the Audio Described "genre" to the top of the list. Brilliant! https://m.youtube.com/watch?t=981&v=N_QjBc_Zuts&feature=youtu.be These series of tweets tend to be fairly technical but as John says, a big part of creating great accessible user experiences is about "being kind", about caring about your users and customers to come up with great features like this one.: https://accessibilityupto11.com/365-days-ios-accessibility/day-091 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-091.md - Day 90: When to tweak button accessibility labels — Buttons with a title, use it as its default accessibility label. Most cases, that's just perfect. But there's a few times that you might want to tweak it. Maybe the image is part of what the button does, or the text in the title is not very clear.: https://accessibilityupto11.com/365-days-ios-accessibility/day-090 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-090.md - Day 89: Update accessibilityLabel when toggling — Sometimes, buttons change meaning, for example when toggled. An example is a play button, tap it and it becomes a pause button. In such case, updating its accessibility label will be clearer than trying to convey the change with traits or values.: https://accessibilityupto11.com/365-days-ios-accessibility/day-089 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-089.md - Day 88: When to use semanticGroup containers — Here's a few examples where Apple seems to use the semanticGroup accessibilityContainerType, other than for the tab bar and toolbar, to serve for inspiration on when it might be useful in your own apps. Reminder that this configuration causes for VoiceOver to announce the accessibility label of the container view, before what it would normally announce for an element, only when the focus moves from outside to inside the container.: https://accessibilityupto11.com/365-days-ios-accessibility/day-088 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-088.md - Day 87: Announce tab bars and toolbars like Apple — VoiceOver announces "Tab bar" or "Toolbar", the first time you select an element in one of these components. If you are implementing your custom versions of these, you can mirror this behaviour, as seen in previous tweets. https://x.com/dadederk/status/1558045414082871298?s=20&t=LA95j22apvWsUqShqWGBzA: https://accessibilityupto11.com/365-days-ios-accessibility/day-087 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-087.md - Day 86: Add context with accessibilityContainerType — Have you noticed that the first time you select an element on Apple Podcast's mini player, VoiceOver says "Mini player", and then, it describes the selected element? It gives the user more context on what "feature" those elements belong to. This can be achieved in UIKit by configuring the accessibility container type of the mini player with .semanticGroup and giving it an accessibility label, in this case: "Mini player". https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilitycontainertype https://developer.apple.com/documentation/uikit/uiaccessibilitycontainertype/semanticgroup: https://accessibilityupto11.com/365-days-ios-accessibility/day-086 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-086.md - Day 85: Expand hit targets with accessibilityFrame — The accessibilityFrame is, by default, the frame of the accessible element. But you can change it. For example, you could expand it, so the interaction area is larger and easier to interact with, and so the user finds less "dead space" in the app.: https://accessibilityupto11.com/365-days-ios-accessibility/day-085 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-085.md - Day 84: Label switches in settings table cells — It is very important to label switches properly and avoid duplication when you find them in table views, like in settings. One way it's usually done, and probably the simplest solution, is by adding the UISwitch in the accessory view of the cell.: https://accessibilityupto11.com/365-days-ios-accessibility/day-084 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-084.md - Day 83: Group a UILabel with its UISwitch — Very often we need to show a UISwitch preceded with a UILabel that explains what it does. The text in the label is basically the accessibility label for the switch. Ideally we want for both components to be grouped behave as a UISwitch. It makes much easier to understand what the switch does, compared to having two separate accessible components. There is a number of ways you can do that. One of them is to use a container view and proxy the switch accessibility attributes.: https://accessibilityupto11.com/365-days-ios-accessibility/day-083 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-083.md - Day 82: Fix traversal order with accessibilityElements — It is possible to change the traversing order of accessibility elements by configuring the accessibilityElements array. You should try to avoid it, but one good reason for doing it is if the default order is illogical because of the visual layout.: https://accessibilityupto11.com/365-days-ios-accessibility/day-082 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-082.md - Day 81: Traverse children with shouldGroupAccessibilityChildren — By its name, I misunderstood what shouldGroupAccessibilityChildren does the first time I saw it. It can be used for VoiceOver to traverse all items in a view before moving to the next one, instead of grouping as in combining those elements. VoiceOver traverses elements in the natural reading order, from left to right, top to bottom, in left-to-right languages. Sometimes data is displayed in columns, so that order might not be the most logical one. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/shouldgroupaccessibilitychildren: https://accessibilityupto11.com/365-days-ios-accessibility/day-081 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-081.md - Day 80: Compose accessibility labels from optionals — This is a small trick I use to compose complex accessibility labels/values when, for a UI component, some elements might not be in all its instances. An array of optional Strings, compact map, and join all elements by a separator, like a comma.: https://accessibilityupto11.com/365-days-ios-accessibility/day-080 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-080.md - Day 79: screenChanged vs layoutChanged notifications — If both screenChanged and layoutChanged notifications signal changes in the UI and allow you to move VoiceOver's focus somewhere else, what's the difference? To the user, screen changed plays a sound indicating them they got moved to a new screen.: https://accessibilityupto11.com/365-days-ios-accessibility/day-079 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-079.md - Day 78: Queue VoiceOver announcements — If you need to send announcement notifications that can step into each other, they will by default, interrupt ongoing announcements. But you can pass attributed strings as parameters too, letting you specify announcements to be queued.: https://accessibilityupto11.com/365-days-ios-accessibility/day-078 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-078.md - Day 77: Announce off-screen updates with notifications — It can help to alert the user of something that happened, in a part of the screen that is not currently on focus, and that is not important enough to disrupt the user by moving VoiceOver’s focus to a different place. It can be useful to announce certain messages like errors or long running tasks that have finished (i.e. a download that finished) or with custom notifications and snack bars.: https://accessibilityupto11.com/365-days-ios-accessibility/day-077 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-077.md - Day 76: Move VoiceOver focus when UI expands — Sometimes, you change your app's UI to offer more options as a result of a user's action. And in such cases, it might be a good idea to move VoiceOver's focus to these new options. We can do that by sending a layout changed notification.: https://accessibilityupto11.com/365-days-ios-accessibility/day-076 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-076.md - Day 75: Move VoiceOver focus on modal present — Even when setting a view as modal for accessibility, you may notice that VoiceOver's focus stays in the same place, instead of moving to the presented view. You can post a screen changed notification and pass the view that should get the focus.: https://accessibilityupto11.com/365-days-ios-accessibility/day-075 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-075.md - Day 74: Trap VoiceOver in overlays with accessibilityViewIsModal — When presenting a UI component that overlays the existing UI, you may have found that VoiceOver starts to randomly jump between the overlaid UI and the elements underneath. To avoid that, you can set its accessibilityViewIsModal to true. When setting the accessibilityViewIsModal to true for a view, VoiceOver will ignore its sibling views, treating it as if it was a modal. Useful when presenting custom popups, popovers, modals, action sheets, etc. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilityviewismodal: https://accessibilityupto11.com/365-days-ios-accessibility/day-074 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-074.md - Day 73: isAccessibilityElement vs accessibilityElementsHidden — What is the difference between isAccessibilityElement and accessibilityElementsHidden? The first one makes the view not accessible, but its subviews can still be accessible. The second one hides the view and all its subviews from assistive tech.: https://accessibilityupto11.com/365-days-ios-accessibility/day-073 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-073.md - Day 72: Hide views with accessibilityElementsHidden — If you need for a view (and all its subviews) not to be focusable by assistive tech like VoiceOver, you can set its accessibilityElementsHidden property to true. This isn't needed very often, but it can be useful for certain custom experiences.: https://accessibilityupto11.com/365-days-ios-accessibility/day-072 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-072.md - Day 71: APIs that work across assistive technologies — The Accessibility APIs are generic and flexible. They're not just for VoiceOver. If you implement them right, you can do it once and it will very likely work great for VoiceOver, Voice Control, Switch Control, Full Keyboard Access, and more. That's why, to start with, we tend to focus on VoiceOver, the same way you may focus on keyboard navigation for the web. A great VoiceOver experience will get you most of the way to a good experience with the other assistive technologies. We've seen one example with Custom Actions. One implementation works for: VoiceOver: https://x.com/dadederk/status/1550099327053451266 Switch Control: https://x.com/dadederk/status/1551236244088279040 Full Keyboard Access: https://x.com/dadederk/status/1551874732504629249 And Voice Control: https://x.com/dadederk/status/1552253520182640645 Of course that doesn't mean you don't have to test and check how the experience is with the other technologies. But before feeling overwhelmed, or for small teams, making sure your app works for VoiceOver is a great start.: https://accessibilityupto11.com/365-days-ios-accessibility/day-071 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-071.md - Day 70: Custom actions with Voice Control — Custom actions work with VoiceOver, Switch Control and Full Keyboard Access. They also do for Voice Control. You can say "Show actions for <item name/number>", and an action sheet with all options, numbered, will be presented to the user. For some use-cases, Voice Control users might not feel it is a big win. Navigation is not as big of an issue, and interacting with custom actions might be a bit trickier than with "exposed" buttons. But lots of times seems a fair compromise.: https://accessibilityupto11.com/365-days-ios-accessibility/day-070 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-070.md - Day 69: Custom actions with Full Keyboard Access — Custom actions work well with VoiceOver and Switch Control. It is also a way of speeding up navigation, and grouping all actions available for an item in a single place, with Full Keyboard Access. Focus an item and use the shortcut Tab (⇥) + Z.: https://accessibilityupto11.com/365-days-ios-accessibility/day-069 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-069.md - Day 68: Add images to UIAccessibilityCustomAction — Since iOS 14, UIAccessibilityCustomAction has an initialiser that accepts an image, as well as a name and action handler. Configuring one will make your custom actions easier to spot in the Switch Control menu. https://developer.apple.com/documentation/uikit/uiaccessibilitycustomaction/init(name:image:actionhandler:): https://accessibilityupto11.com/365-days-ios-accessibility/day-068 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-068.md - Day 67: Custom actions work in Switch Control — Custom actions work as great on Switch Control as they do in VoiceOver. It makes navigation much, much, faster and you’ll be able to find all those custom actions in the Switch Control menu.: https://accessibilityupto11.com/365-days-ios-accessibility/day-067 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-067.md - Day 66: Reduce clutter by grouping with custom actions — Potential benefits from grouping logical pieces of information and moving buttons to custom actions: reduce redundancy (by removing repetitive controls) and reduce cognitive load (by making easier to know what item will be affected by each action): https://accessibilityupto11.com/365-days-ios-accessibility/day-066 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-066.md - Day 65: Custom actions for hidden swipe gestures — Custom actions are also great for actions that are executed with a gesture that is overridden by VoiceOver. Think of the unread, flag and archive hidden options that you can make visible by swiping left/right on a message row in the Mail app.: https://accessibilityupto11.com/365-days-ios-accessibility/day-065 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-065.md - Day 64: Reach grouped buttons with custom actions — Optimising for navigation by making a view accessible shouldn’t come at the expense of the buttons in it not being accessible. Configuring custom actions will allow the user to access them using the Actions rotor. With the Actions rotor, users can swipe up and down to cycle through all the options, stop at the desired one, and double tap to execute that action. You can configure an array of custom actions. Custom actions can have a name that will be announced by VoiceOver and an action handler or target selector with the code that will be executed. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilitycustomactions: https://accessibilityupto11.com/365-days-ios-accessibility/day-064 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-064.md - Day 63: Group cells for faster VoiceOver navigation — Sometimes you want to prioritise ease of navigation, and that's when configuring isAccessibilityElement to true on a container view makes sense. This is especially true in table/collection views and with complex cells with lots of elements. Take the example from a tweet (from Day 62's tweet). If the tweet has 9 accessible elements, you'd need 9 swipes to the right to go to the next tweet in the list. But ideally, I single swipe should be enough. https://x.com/dadederk/status/1549417799746994177 On the other hand, for the detail screen for a single tweet, you want to optimise for ease of access to each one of the elements, instead of navigation. In that case it would be better for the tweet view not to be an accessibility element.: https://accessibilityupto11.com/365-days-ios-accessibility/day-063 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-063.md - Day 62: isAccessibilityElement hides child elements — When setting isAccessibilityElement to true, assistive tech like VoiceOver will stop looking for other accessible elements in that view hierarchy. So if we make a view accessible, its subviews, including buttons and labels won't be accessible.: https://accessibilityupto11.com/365-days-ios-accessibility/day-062 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-062.md - Day 61: Dismiss with accessibilityPerformEscape — To capture the gesture, you can override the accessibilityPerformEscape() function. In there you can dismiss your view, and return true if you could successfully handle it. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilityperformescape(): https://accessibilityupto11.com/365-days-ios-accessibility/day-061 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-061.md - Day 60: Implement Magic Tap with accessibilityPerformMagicTap — VoiceOver has a very cool gesture called the Magic Tap (double tap with two fingers). It should execute the most important task for the current state of the app. Examples: start/stop timer, play/pause music, take a photo, compose a tweet... You just need to override accessibilityPerformMagicTap() to capture that gesture, execute the desired code, and return true if handled successfully. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilityperformmagictap(): https://accessibilityupto11.com/365-days-ios-accessibility/day-060 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-060.md - Day 59: Please don't use accessibility labels as UI test IDs — Please, don't use accessibility labels as ids for your UI tests. It can completely ruin the experience for VoiceOver users. There is actually an accessibility identifier property that you can use instead to uniquely identify your UI elements.: https://accessibilityupto11.com/365-days-ios-accessibility/day-059 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-059.md - Day 58: Meet Apple's 44×44 minimum tap targets — Apple recommends in their guidelines a minimum tappable area size of 44x44 points for all controls. A lot of times this can be corrected in an app without changing how it looks, but making it objectively easier to interact with for everyone.: https://accessibilityupto11.com/365-days-ios-accessibility/day-058 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-058.md - Day 57: Text and background color contrast matters — Color contrast between text and background is very important for perceivability. As colors come closer to each other, they’re more difficult to distinguish. Notice that colors that work well with big font sizes may not for smaller text.: https://accessibilityupto11.com/365-days-ios-accessibility/day-057 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-057.md - Day 56: Override labels for NSTextAttachment icons — It is possible to embed icons within text using NSTextAttachment and NSAttributedString. If you do, please remember to override the accessibility label, otherwise VoiceOver will announce it as "Attachment.png File". Example code in the image: ```swift let magnifyingGlassIcon = UIImage(systemName: "magnifyingglass")! let searchButton = UIButton() let searchTutorialLabel = UILabel() searchButton.accessibilityLabel = "search" let textAttachment = NSTextAttachment(image: magnifyingGlassIcon) let string = "Select the button to find elements in the list" let attributedString = NSMutableAttributedString(string: string) let attributedStringIcon = NSAttributedString(attachment: textAttachment) let iconPlaceholderRange = attributedString.string.range(of: "")! let iconRange = NSRange(iconPlaceholderRange, in: attributedString.string) attributedString.replaceCharacters(in: iconRange, with: attributedStringIcon) searchTutorialLabel.attributedText = attributedString searchTutorialLabel.accessibilityLabel = string.replacingCharacters(in: iconPlaceholderRange, with: searchButton.accessibilityLabel!) ```: https://accessibilityupto11.com/365-days-ios-accessibility/day-056 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-056.md - Day 55: Include icon state in labels and values — When thinking about accessibility labels and values, it is easy to miss adding information or state that are represented by little visual cues and icons: a checkmark indicating something has been played, a down arrow indicating a downward trend...: https://accessibilityupto11.com/365-days-ios-accessibility/day-055 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-055.md - Day 54: Convey state with color, haptics, and icons — Convey important information in multiple modes (sounds, haptics, colour, iconography, messaging...) so no-one misses it. Take Spotify's shuffle button. It is green when on, white when off, but it has also a dot indicator. https://wearecolorblind.com/examples/spotify-shuffle-and-repeat-buttons/: https://accessibilityupto11.com/365-days-ios-accessibility/day-054 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-054.md - Day 53: Handle VoiceOver double tap with accessibilityActivate — accessibilityActivate() lets you capture a VoiceOver double tap. This is useful if you are creating a custom component you interact with using complex gestures or VoiceOver navigation gestures. An example: slide to unlock. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilityactivate(): https://accessibilityupto11.com/365-days-ios-accessibility/day-053 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-053.md - Day 52: UIColor accessibilityName for color labels — Since iOS 14, you can get a human readable localised name for a UIColor, with a very useful property called accessibilityName, that you can use in accessibility attributes like labels or values. How cool is that? https://developer.apple.com/documentation/uikit/uicolor/accessibilityname: https://accessibilityupto11.com/365-days-ios-accessibility/day-052 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-052.md - Day 51: Apple's guidelines for accessibilityHint — Guidelines from Apple: Begin with a verb that explains the results of the action. Avoid using the imperative form of a verb because that can make it sound like a command. Don’t include the action type. Don’t include the control. https://developer.apple.com/documentation/objectivec/nsobject-swift.class/accessibilityhint: https://accessibilityupto11.com/365-days-ios-accessibility/day-051 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-051.md - Day 50: Labels, traits, and values for the same experience — A similar experience can sometimes be achieved in different ways using labels, traits, and values. Most times there are no right or wrong answers; it will be up to your users to say which approach they like the most. Two great pieces of advice though: > **@Sommer:** "Check and see how Apple's own apps handle similar scenarios. Not because our apps are perfect but rather to help build on consistent patterns." > > Tweet by @Sommer > **@dotjay:** "Meet the platform expectations, and give users control rather than prescribing what you think users want." > > Tweet by @dotjay: https://accessibilityupto11.com/365-days-ios-accessibility/day-050 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-050.md - Day 49: Manage traits with Swift OptionSet — In Objective-C accessibility traits are a bitmask. Some devs find tricky to work with them using bitwise operations. In Swift they conform to the OptionSet protocol that conforms to SetAlgebra. That means you can simply insert/remove traits.: https://accessibilityupto11.com/365-days-ios-accessibility/day-049 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-049.md - Day 48: accessibilityValue conveys control state — Accessibility values are about state. Using them appropriately will make the experience better for Voice Control users. Think of a repeat button (values could be: off, one or all songs) or a notifications tab (value could be: x new items). For more on accessibility values, check out this fantastic blog post from @MobileA11y with info on the APIs (UIKit, SwiftUI), accessibility attributed values, WCAG, or some more examples (text in a text field, value on a stepper or slider). https://mobilea11y.com/blog/accessibility-values/: https://accessibilityupto11.com/365-days-ios-accessibility/day-048 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-048.md - Day 47: summaryElement announces on app launch — The .summaryElement accessibility trait causes VoiceOver to announce that element when the app starts. The element won't get the focus though, and the order is not affected. A candidate for this trait could be the rings info in the Activity app.: https://accessibilityupto11.com/365-days-ios-accessibility/day-047 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-047.md - Day 46: playsSound for buttons with sound effects — There is another accessibility trait: .playsSound, that does a similar thing than .startsMediaSession. This one seems more suitable for buttons that have their own sound effects when interacting with them, like it often happens in games.: https://accessibilityupto11.com/365-days-ios-accessibility/day-046 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-046.md - Day 45: startsMediaSession avoids label repetition — When interacting with a button with VoiceOver, the accessibility label is repeated to the user. If you are playing some audio, it could be difficult to listen to it properly. To avoid that, you can add the .startsMediaSession accessibility trait.: https://accessibilityupto11.com/365-days-ios-accessibility/day-045 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-045.md - Day 44: Mark decorative images as non-accessible — If an image does not convey additional information, maybe it's just used to make the UI look more attractive, it makes sense for VoiceOver to skip it. UIKit: set isAccessibilityElement to false. SwiftUI: create a decorative image explicitly.: https://accessibilityupto11.com/365-days-ios-accessibility/day-044 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-044.md - Day 43: image trait unlocks Image Explorer — Images that convey important information should have the .image accessibility trait and provide an alternative text in the accessibility label. "Image" will be added to VoiceOver's utterance and the user will be able to use Image Explorer. Image Explorer is fairly new, introduced just a couple years ago. But if you were appropriately configuring the image trait, users suddenly got this new functionality for free. Isn't that awesome? With VoiceOver on, open Image Explorer by swiping up in an image and double tapping. It lets users find people (with a basic description and positioning in the photo), objects or text in images, using on-device intelligence. It is very cool!: https://accessibilityupto11.com/365-days-ios-accessibility/day-043 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-043.md - Day 42: tabBar trait for custom tab bars — I'll never recommend creating a custom component if there is a native one that does the job. But if you develop a custom tab bar, .tabBar accessibility trait comes to the rescue. Apply to a container view and its buttons will be announced as tabs.: https://accessibilityupto11.com/365-days-ios-accessibility/day-042 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-042.md - Day 41: keyboardKey trait for custom keypads — There is an accessibility trait for defining something that represents a custom keyboard's key: .keyboardKey. It allows VoiceOver users to change the typing mode to Direct touch typing. The calculator app or an access pin pad, are some examples.: https://accessibilityupto11.com/365-days-ios-accessibility/day-041 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-041.md - Day 40: Playing piano with VoiceOver: allowsDirectInteraction — Imagine playing a piano with VoiceOver. You'd have to find the key you want to play and then double tap. It would be a very difficult experience. With the .allowsDirectInteraction accessibility trait, VoiceOver passes through touch gestures. Use carefully! And only when it really makes sense to be able to handle controls directly with touch. Other examples could be a drawing app or some games.: https://accessibilityupto11.com/365-days-ios-accessibility/day-040 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-040.md - Day 39: Tune VoiceOver slider adjustment increments — When implementing a UISlider, it is a good idea to consider how much the slider value should change when swiping up/down to adjust it. It might not always make sense to do it in 10% increments, which is the default behaviour. Could be because the value at those intervals doesn't make sense, or feel random, or because it wouldn't provide the user with a fine enough control being able to go through the whole slider in just 10 swipes. It user will still be able to adjust the slider to any value by double tapping and holding and then moving the finger left or right, bypassing VoiceOver gestures. VoiceOver announces the new value as it changes.: https://accessibilityupto11.com/365-days-ios-accessibility/day-039 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-039.md - Day 38: notEnabled trait for disabled controls — Do you know when a UI element is greyed out to show that it is disabled? Yes, there is an accessibility trait for that too: .notEnabled. VoiceOver will say “dimmed” after its accessibility label and Voice Control and Switch Control will skip it.: https://accessibilityupto11.com/365-days-ios-accessibility/day-038 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-038.md - Day 37: selected trait announces before the label — The .selected accessibility trait indicates when an element has been selected. You’ll notice that VoiceOver announces “selected” before the accessibility label. You can find that in the system for the selected tab in the tab bar, for example.: https://accessibilityupto11.com/365-days-ios-accessibility/day-037 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-037.md - Day 36: updatesFrequently for live changing content — If you want to update the VoiceOver user frequently about how a component is changing, when focused, you can use the .updatesFrequently accessibility trait. A downloading progress bar, a stock value, or a timer, are some examples.: https://accessibilityupto11.com/365-days-ios-accessibility/day-036 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-036.md - Day 35: searchField trait for custom search bars — Styling a search bar is hard. Lots of developers opt to build their own instead. If you do, remember to add the .searchField accessibility trait. VoiceOver will announce "Search Field" indicating the user that results might change as they type.: https://accessibilityupto11.com/365-days-ios-accessibility/day-035 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-035.md - Day 34: Meaningful accessibilityValue for sliders — UISliders are adjustable, and its default accessibility value is represented in percentages. But that's not always the best format to express a value. Consider a slider to select a distance radius. Miles or km seem a more appropriate unit. Example code in the image: ```swift override var accessibilityValue: String? { get { let formatter = MeasurementFormatter() let measurement = Measurement( value: Double(value), unit: .kilometers ) formatter.unitStyle = .long return formatter.string(from: measurement) } set {} } ```: https://accessibilityupto11.com/365-days-ios-accessibility/day-034 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-034.md - Day 33: Implement accessibilityIncrement and Decrement — With VoiceOver, you can swipe up/down to increase/decrease the value of adjustable components. You need to implement accessibilityIncrement() and accessibilityDecrement() accordingly, and configure an accessibility value that makes sense. Example code in the image: ```swift override func accessibilityIncrement() { guard value < 5 else { return } value += 1 accessibilityValue = "\(value) of 5" sendActions(for: .valueChanged) } override func accessibilityDecrement() { guard value > 1 else { return } value -= 1 accessibilityValue = "\(value) of 5" sendActions(for: .valueChanged) } ``` Links to the official documentation: * accessibilityincrement() * accessibilitydecrement(): https://accessibilityupto11.com/365-days-ios-accessibility/day-033 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-033.md - Day 32: Adjustable trait for custom value controls — If you are developing a custom component, that can change value, chances are that it will need the adjustable accessibility trait (VoiceOver will say: "Adjustable"). Think of a component that lets you rate from one to five thumbs up (or stars).: https://accessibilityupto11.com/365-days-ios-accessibility/day-032 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-032.md - Day 31: Hacks are accessibility's worst enemy — Hacks are accessibility’s worst enemy. An example. There is a ‘trick’ floating on the internet: if you want a button with an icon to the right of the text, set the semantic content attribute to force right to left. Great way to create focus traps.: https://accessibilityupto11.com/365-days-ios-accessibility/day-031 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-031.md - Day 30: Embedded links in UITextView with VoiceOver — If you need multiple links embedded in some text (like the classic T&Cs and Privacy policy), the easiest is to use a UITextView & Attributed Strings, and it will work beautifully with VoiceOver. You'll be even able to navigate through links. In the example, VoiceOver would say: “I agree with the Privacy Policy and the Terms and Conditions, link”. Swipe down, should announce: “Privacy Policy, link” and you can double tap to open it. Swiping down one more time announces: “Terms and Conditions, link”. Example code in the image: ```swift let textView = UITextView() let string = "I agree with the Privacy Policy and the Terms and Conditions" let attributedString = NSMutableAttributedString(string: string) attributedString.addAttribute(.link, value: "https://www.yourdomain.com/pp", range: NSRange(location: 17, length: 14)) attributedString.addAttribute(.link, value: "https://www.yourdomain.com/tac", range: NSRange(location: 40, length: 20)) textView.attributedText = attributedString extension ViewController: UITextViewDelegate { func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { UIApplication.shared.open(URL) return true } } ```: https://accessibilityupto11.com/365-days-ios-accessibility/day-030 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-030.md - Day 29: The link accessibility trait — The link accessibility trait is applied to UI elements that open some web content. It usually appears in-line in the content and represented by underlined text, but not always. VoiceOver will say "link" after the accessibility label.: https://accessibilityupto11.com/365-days-ios-accessibility/day-029 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-029.md - Day 28: Header trait is an easy accessibility win — Configuring the header accessibility trait, when appropriate, is one of my favourite accessibility quick wins. In this example, you need a single swipe down, instead of 12 swipes to the right to get to from Podcasts to Artists, in the app.: https://accessibilityupto11.com/365-days-ios-accessibility/day-028 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-028.md - Day 27: Header trait speeds up VoiceOver navigation — The header accessibility trait makes VoiceOver announce something as a header. More importantly, it lets the user navigate through headings, swiping up/down, significantly speeding up navigation and making it easier to explore/discover content.: https://accessibilityupto11.com/365-days-ios-accessibility/day-027 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-027.md - Day 26: Meet the VoiceOver rotor — Meet the rotor. A menu that you activate (and change options) by rotating two fingers on the screen. It lets you select different navigation modes and customizations. Like navigating through headings or changing VoiceOver’s speaking rate.: https://accessibilityupto11.com/365-days-ios-accessibility/day-026 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-026.md - Day 25: Configure button trait on custom controls — If, for some reason, you are creating a button from scratch, instead of relying on UIButton (perhaps you are adding a fancy micro interaction animation?), take into account that you’ll need to configure the button accessibility trait.: https://accessibilityupto11.com/365-days-ios-accessibility/day-025 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-025.md - Day 24: Disclosure indicators add the button trait — If a table view cell has a disclosure indicator accessory type configured, the button trait gets added automatically. A good reminder that when following Apple's Human Interface Guidelines, things are more accessible out of the box.: https://accessibilityupto11.com/365-days-ios-accessibility/day-024 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-024.md - Day 23: Add the button trait to table cells — A common example where you need to manually configure the button accessibility trait is for some table/collection view cells. These tend to be “buttons” that perform an action, like playing music, or bring the user to a different screen.: https://accessibilityupto11.com/365-days-ios-accessibility/day-023 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-023.md - Day 22: The button accessibility trait in VoiceOver — With the button trait VoiceOver will read “button” after the accessibility label and will indicate the user that, when focused, they can double tap anywhere on the screen to interact with it. UIButton has this trait by default.: https://accessibilityupto11.com/365-days-ios-accessibility/day-022 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-022.md - Day 21: Combine multiple accessibility traits — A component can have more than one accessibility trait, they can be combined. A heading can be a button too, for example. Or a button could be selected. You can insert or remove the selected trait to the button, when needed.: https://accessibilityupto11.com/365-days-ios-accessibility/day-021 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-021.md - Day 20: What accessibility traits tell VoiceOver users — An accessibility trait is the role of the component. Among other things, it gives the user information on how they can interact (or not) with it. When using VoiceOver, the trait is usually (not always) read after the accessibility label. At the time of writing this tweet, there are 18 different accessibility traits: https://developer.apple.com/documentation/uikit/uiaccessibilitytraits Some examples are: button, header, selected, adjustable or not enabled.: https://accessibilityupto11.com/365-days-ios-accessibility/day-020 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-020.md - Day 19: WWDC22 kicks off with accessibility news — Today starts the . Apple announces what new APIs we'll be able to use to make more inclusive and accessible apps. There's also Labs, Digital Lounges and Sessions, for free. Check out the schedule here: https://developer.apple.com/wwdc25/topics/accessibility-inclusion/ Last year, Apple presented Audio Graphs to make graphs more accessible. This year, they introduced Swift Charts, that lets you build a wide variety of charts in SwiftUI and they have great VoiceOver support. https://developer.apple.com/documentation/Charts @dnlyong has a great thread going through lots of the new accessibility features presented this year. https://x.com/dnlyong/status/1533897274274639873 As noted by @RobRWAPP and @mecid, Apple is tweaking the style of the SwiftUI accessibility modifiers. https://x.com/RobRWAPP/status/1533900962615762945 Sessions this year include topics like gaming (with Unity), localisation and internationalisation. You can check these (as they get published during the week) and previous accessibility sessions here: https://developer.apple.com/videos/accessibility-inclusion/ SwiftUI lets you now add multiple accessibility actions at once and quick actions to be show by the system when active: https://developer.apple.com/documentation/swiftui/view/accessibilityactions(_:)?changes=latest_minor https://developer.apple.com/documentation/swiftui/view/accessibilityquickaction(style:content:)?changes=latest_minor: https://accessibilityupto11.com/365-days-ios-accessibility/day-019 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-019.md - Day 18: Add a label to custom loading indicators — Do you have a fancy custom loading animation instead of an UIActivityIndicatorView? You may want to check if it has an accessibility label so a VoiceOver user knows that something is happening. Something like "In progress" or "Loading" could work.: https://accessibilityupto11.com/365-days-ios-accessibility/day-018 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-018.md - Day 17: Detect when VoiceOver is running — You can check if some features, like VoiceOver, are on. Experiences should not diverge too much. It could be used to avoid auto-hiding UI elements. iOS probably checks this to show search fields by default, without having to pull them down. From the documentation: isVoiceOverRunning: https://developer.apple.com/documentation/uikit/uiaccessibility/isvoiceoverrunning: https://accessibilityupto11.com/365-days-ios-accessibility/day-017 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-017.md - Day 16: Better relative date and weekday labels — Two more examples on better accessibility labels for abbreviations. "4 days ago" is better than "4 D", with a RelativeDateTimeFormatter and a spellOut units style. "Monday" is better than "Mon", accessing the weekdaySymbols from a Calendar. Some useful links: Relative Date Time Formatter: https://developer.apple.com/documentation/foundation/relativedatetimeformatter Units Style: https://developer.apple.com/documentation/foundation/relativedatetimeformatter/unitsstyle-swift.enum/spellout Weekday symbols: https://developer.apple.com/documentation/foundation/calendar/weekdaysymbols: https://accessibilityupto11.com/365-days-ios-accessibility/day-016 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-016.md - Day 15: Use formatters for abbreviation labels — Tip for abbreviations. Something like "3h 24m" will be read by VoiceOver as "3 h 24 meters". Formatters can help. DateComponentsFormatter with a "spellOut" units style will give you a more suitable label: "three hours, twenty-four minutes" Example code in the image: ```swift let dailyAverageLabel = UILabel() let abbreviatedReadableFormatter = DateComponentsFormatter() abbreviatedReadableFormatter.allowedUnits = [.hour, .minute] abbreviatedReadableFormatter.unitsStyle = .spellOut let abbreviatedReadableDuration = abbreviatedReadableFormatter.string(from: 12240) dailyAverageLabel.accessibilityLabel = abbreviatedReadableDuration ``` Some useful links: * Date Components Formatter: * Units Style: By the way! Formatters are also great for localisation.: https://accessibilityupto11.com/365-days-ios-accessibility/day-015 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-015.md - Day 14: Don't break Voice Control when tweaking labels — Accessibility labels are not just for VoiceOver. If you tweak how they sound by changing spelling, adding spaces, etc. you could be making the experience worse for Voice Control and Braille display users. Attributed accessibility labels can help.: https://accessibilityupto11.com/365-days-ios-accessibility/day-014 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-014.md - Day 13: Speak punctuation with accessibilitySpeechPunctuation — With the attribute accessibilitySpeechPunctuation, you can ask VoiceOver to speak any punctuation marks in your attributed accessibility label, if that is what you want. Good for code snippets?: https://accessibilityupto11.com/365-days-ios-accessibility/day-013 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-013.md - Day 12: Spell out codes with accessibilitySpeechSpellOut — accessibilitySpeechSpellOut asks VoiceOver to speak the sequence of characters. Can be useful for things like promo/reference/authentication codes, phone numbers... it makes more sense to announce each character rather than words and big numbers. Example code in the image: ```swift let codeLabel = UILabel() let attributedLabel = NSAttributedString( string: "BAC1234567D", attributes: [.accessibilitySpeechSpellOut: true] ) title.accessibilityAttributedLabel = attributedLabel ```: https://accessibilityupto11.com/365-days-ios-accessibility/day-012 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-012.md - Day 11: Emphasize labels with accessibilitySpeechPitch — accessibilitySpeechPitch lets you emphasise something changing VoiceOver's pitch. The value goes from 0.0 to 2.0. The default is 1.0. Twitter could change pitch to read hashtags, for example, avoiding repetition but still signalling they're there.: https://accessibilityupto11.com/365-days-ios-accessibility/day-011 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-011.md - Day 10: IPA notation so VoiceOver says paella right — accessibilitySpeechIPANotation is useful for indicating how foreign words are pronounced. It really annoys me to hear the word paella constantly mispronounced 😁. You could also specify language, but this way, VoiceOver won't change its voice. Example code in the image: ```swift let recipeNameLabel = UILabel() let attributedLabel = NSAttributedString( string: "Paella", attributes: [.accessibilitySpeechIPANotation: "pɑːˈeɪə"] ) recipeNameLabel.accessibilityAttributedLabel = attributedLabel ```: https://accessibilityupto11.com/365-days-ios-accessibility/day-010 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-010.md - Day 9: IPA for homographs and your app name — accessibilitySpeechIPANotation is sometimes handy in English where a word is spelled the same but pronounced differently depending of the context. Some examples are: live, read... Or you may want to correct how VoiceOver pronounces your app's name! Example code in the image: ```swift let liveNewsChannelView = UIView() let attributedLabel = NSMutableAttributedString(string: "24 hour news channel. ") attributedLabel.append(NSAttributedString(string: "Live",attributes: [.accessibilitySpeechIPANotation: "laɪv"])) liveNewsChannelView.accessibilityAttributedLabel = attributedLabel ```: https://accessibilityupto11.com/365-days-ios-accessibility/day-009 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-009.md - Day 8: Fix pronunciation with accessibilitySpeechIPANotation — An interesting speech attribute for attributed accessibility labels is accessibilitySpeechIPANotation that lets you specify how VoiceOver should pronounce a label with the International Phonetic Alphabet (IPA) notation. https://developer.apple.com/documentation/foundation/nsattributedstring/key/accessibilityspeechipanotation: https://accessibilityupto11.com/365-days-ios-accessibility/day-008 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-008.md - Day 7: Multilingual labels with speech attributes — With attributed accessibility labels, your app could now, for example, greet your users in different languages. Note that it will change to the voice of the corresponding language you are switching to. Example code in the image: ```swift let greetingLessonView = UIView() let bcp47LanguageCode = "es-Es" let translatedPhrase = "¡Buenos días! " let attributedLabel = NSMutableAttributedString(string: translatedPhrase,attributes: [.accessibilitySpeechLanguage: bcp47LanguageCode]) attributedLabel.append(NSAttributedString(string: "Means: good morning!")) greetingLessonView.accessibilityAttributedLabel = attributedLabel ```: https://accessibilityupto11.com/365-days-ios-accessibility/day-007 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-007.md - Day 6: Attributed accessibility labels are a thing — Attributed accessibility labels are a thing! They'll let you specify (for the whole accessibility label or a portion of it) VoiceOver's language, to read punctuation marks, spell it out, correct the pronunciation, or even change the pitch. @RobRWAPP has a very detailed blog post explaining each one of these attributes: https://mobilea11y.com/blog/attributed-accessibility-labels/ And here's Apple's official documentation for them: https://developer.apple.com/documentation/uikit/speech-attributes-for-attributed-strings: https://accessibilityupto11.com/365-days-ios-accessibility/day-006 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-006.md - Day 5: Label image-only buttons for VoiceOver — Believe it or not, one of the most common accessibility pitfalls I see in iOS apps, is forgetting to configure a suitable accessibility label for buttons with just an image (no title), resulting in VoiceOver saying just: "button". Why for buttons with just an image? If it has a title, the accessibility label gets inferred from it. So here's one that should be very easy for you to find and fix in your app. No more apps that just say: button, button, button, button...! If you are looking for the best explanation on what makes, not good, but great accessibility labels, I really recommend “Writing Great Accessibility Labels” by @jordyn2493 at WWDC. The difference between someone using/loving/deleting your app. https://developer.apple.com/videos/play/wwdc2019/254/: https://accessibilityupto11.com/365-days-ios-accessibility/day-005 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-005.md - Day 4: Don't put the control type in accessibilityLabel — Accessibility labels should not contain the type of the control, that's a job for the accessibility trait instead. If you have a button with a label like "Close button" and the ".button" trait, VoiceOver will say: "Close button, button".: https://accessibilityupto11.com/365-days-ios-accessibility/day-004 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-004.md - Day 3: What makes a good accessibilityLabel — Good accessibility labels are at the core of good accessible apps. It should be a localized succinct string that tells as much as possible about the component (without including its type) and provides context avoiding verbosity and redundancy.: https://accessibilityupto11.com/365-days-ios-accessibility/day-003 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-003.md - Day 2: SwiftUI accessibility modifiers match UIKit — SwiftUI has equivalent accessibility modifiers for some of UIAccessibility's properties in UIKit. Same basic concepts apply. Label: https://developer.apple.com/documentation/swiftui/view/accessibilitylabel(_:)-9ek2h Value: https://developer.apple.com/documentation/swiftui/view/accessibilityvalue(_:)-8esl7 Traits: https://developer.apple.com/documentation/swiftui/view/accessibilityaddtraits(_:) Hint: https://developer.apple.com/documentation/swiftui/view/accessibilityhint(_:)-3i2vu: https://accessibilityupto11.com/365-days-ios-accessibility/day-002 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-002.md - Day 1: UIAccessibility: label, value, trait, and hint — UIAccessibility is the cornerstone of any accessible UIKit app. Among others, understanding what an accessibility label, value, trait or hint are, is key. This is an example of how they could be configured for a custom rating component.: https://accessibilityupto11.com/365-days-ios-accessibility/day-001 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-001.md - Day 0: Are you up for 365 days of iOS accessibility? — Tomorrow is @gbla11yday! And I'm going to start a challenge, tweeting everyday, for a whole year, about tips, resources, and other useful info on how to develop accessible iOS apps. Are you up for the challenge?: https://accessibilityupto11.com/365-days-ios-accessibility/day-000 Markdown: https://accessibilityupto11.com/365-days-ios-accessibility/day-000.md ## Feeds and discovery - Main RSS: https://accessibilityupto11.com/feed.rss - 365 Days RSS: https://accessibilityupto11.com/365-days-feed.rss - Sitemap: https://accessibilityupto11.com/sitemap.xml - Curated map: https://accessibilityupto11.com/llms.txt ## Attribution When citing content, credit Daniel Devesa Derksen-Staats and link to the source URL.