Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Accessibility

RSS for tag

Make your apps function for a broad range of users using Accessibility APIs across all Apple platforms.

Posts under Accessibility tag

138 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Markdown Link in AttributedString Not Focusable with Full Keyboard Access in SwiftUI
I’m encountering an accessibility issue in SwiftUI related to keyboard navigation. 🐞 Problem When using an AttributedString to display Markdown content in a SwiftUI view (such as a Text view), any links included in the Markdown are not keyboard focusable when Full Keyboard Access is enabled. This means users can’t navigate to or activate the links using the Tab key or other keyboard-only methods. 💻 Platform iOS version: 16+ Framework: SwiftUI Device: All tested iPhones and iPads 🧪 Steps to Reproduce Enable Full Keyboard Access in iOS settings. Run the included SwiftUI Playground or equivalent app using the code below. Try to navigate to the link using Tab or keyboard arrow keys. Observe that the Markdown link is not reachable via keyboard focus. 🧩 Expected Behavior The Markdown link should be reachable via keyboard focus. It should be possible to activate the link using Space or Return. 📚 Example code struct ContentView: View { let attributedString: AttributedString init() { self.attributedString = try! AttributedString( markdown: "This is a [test link](https://apple.com) inside an attributed string." ) } var body: some View { VStack { Text("Issue: Attributed Markdown Link Is Not Focusable with full keyboard access") .font(.headline) .padding() Text(attributedString) // The link is not focusable with .padding() .border(Color.gray, width: 1) Text("Expected: The link should be focusable with Full Keyboard Access.") .foregroundColor(.red) .padding() } } }
1
2
58
Apr ’25
Unexpected behaviour of hardware keyboard focus in UITests
Hello! I was faced with unexpected behavior of hardware keyboard focus in UITests. A clear description of the problem When running UITests on the iOS Simulator with both "Full Keyboard Access" and "Connect Hardware Keyboard" options enabled, there is a noticeable delay between keyboard actions for focus managing (like pressing Tab or arrow keys). The delay seems to increase with repeated input and suggests that events are being queued instead of processed immediately. I will describe why I have such an assumption later. A step-by-step set of instructions to reproduce the problem Launch the iOS Simulator. Enable both "Full Keyboard Access" and "Connect Hardware Keyboard" in the Simulator settings. Run a UITest on a target application (ideally an endless or long-running test). Once the app is launched, press the Tab key several times. Observe the delay in focus movement. Optionally, press the Tab or arrow keys rapidly, then stop the UITest. After stopping, you’ll see a burst of rapid focus changes. What results you expected We expected keyboard actions (like Tab) to be handled immediately and the UI focus to update smoothly during UITests. What results you saw There was a 4–10 (end more) second delay between pressing keys and seeing a response. All stacked keyboard events (used for managing focus) are performed all at once after stopping the UITest. The version of Xcode you are using Xcode: Version 16.3 (16E140) Simulator: iPhone 16 Pro (iOS 18.4 and 18.1) Simulator: iPad Pro 11-inch (M4) (iPadOS 17.5)
1
2
106
Apr ’25
Using WebSocket for BCI Click Input in VisionOS - FocusState vs. System-Level Limitations
Hi everyone, My team and I are developing an accessibility-focused VisionOS app (MindTap) as part of a university project, aiming to support individuals with Locked-In Syndrome using Brain-Computer Interface (BCI) signals to trigger interactions (e.g., tapping) within the Apple Vision Pro environment. Problem 1: Simulating Eye Tracking in Simulator We are testing onHover with Send pointer to the device under I/O > Input in the simulator, and while it mostly works (a bit laggy), we found that onHover won't function on the actual Vision Pro hardware. From what I understand, we should be using FocusState for proper gaze interaction, but testing this requires the physical device. Is there any workaround or official Apple-recommended way to simulate Focus-based gaze detection without a real Vision Pro? Problem 2: WebSocket-triggered "Click" doesn't work outside the app We successfully use WebSocket to send a custom signal (a "1" from the brain signal device) to trigger an action inside our app. However, when the user opens a third-party app like Apple News, the WebSocket-triggered "click" no longer works. We suspect this is due to sandbox restrictions or lack of system-level permissions. Is it possible in anyway to: Trigger interaction events outside the app using custom input (like BCI via Websocket)? Access system-wide click/tap simulation APIs from within VisionOS apps Integrate this with accessibility services (like Voice Control or AssistiveTouch) We'd appreciate any official guidance or tips from others building similar accessibility apps with alternative input methods in VisionOS. Thanks in advance for any insight you can provide!
0
0
60
Apr ’25
PencilKit on visionOS Doesn’t Support Left-Handed Users? How Can We Customize Hand Roles?
I’m building a visionOS app that uses PencilKit for drawing. Currently, PencilKit defaults to using the right hand for drawing and the left hand for panning, with no apparent way to change this behavior. Some of my users are left-handed, and they naturally want to draw with their left hand and pan with their right. However, PencilKit doesn’t seem to support this interaction pattern. Is there a way to customize which hand does what in PencilKit on visionOS? Or have I missed some API or workaround that would allow support for left-handed users?
1
0
57
Apr ’25
Add VoiceOver touch gesture guidance for frame iframe in webView and Safari web
Please update Accessibility OS Settings for VoiceOver in iPhone iOS and iPadOS to include frames on the Rotor, and to make web navigation and component gestures easier to find and assign. Please add content to the iPhone and iPad Apple User Guide to use VoiceOver in web navigation with touch gestures. Specifically... iframes. There is no clear guidance in Apple documentation for VoiceOver users in iPhone or iPadOS to access iframes with touch gestures. A common belief as written on AppleVis, other blogs, and internet searches is that iframes in Safari or a webView in an app are only available with explore by touch. If explore by touch is the only option for some interactions, that needs to be included in Apple User Guides. If not, details on equivalent touch gestures for VO that have keyboard interactions in Mac need to be clear for users. VoiceOver for Mac includes a default keyboard interaction of VO-Command-F in its extensive User Guide (https://support.apple.com/guide/voiceover/by-images-or-frames-mchlp2740/mac). A user can include a rotor option for web navigation for iframes. VoiceOver for iPhone and iPad does not include a default swipe gesture assigned to frames. An option is not available for the Rotor. While there is iPhone User Guide guidance that gestures can be customized (https://support.apple.com/guide/iphone/customize-gestures-and-keyboard-shortcuts-iph59a8e6fd2/18.0/ios/18.0), it is not clear that for adding this gesture, "Move to the next frame" is tucked into the advanced navigation commands for VoiceOver Accessibility Settings in the OS. At least in my phone, the word "frame" was not searchable despite the All Commands screen using a search bar.
1
0
84
Apr ’25
Handling VoiceOver Focus When Screen Changes (Push, Present, and SplitViewController)
I have some doubts about how VoiceOver handles focus when the screen updates. When a new UIViewController is pushed onto a UINavigationController or presented modally, how does VoiceOver decide which element to focus on? Is there a way to control or customize this behavior? In a UISplitViewController, when an item is selected in the primary view controller, the focus should shift to the relevant content in the secondary view controller. How can we ensure that VoiceOver correctly moves focus to the right element in the secondary panel?
0
0
101
Apr ’25
VisionOS - Gamepad steals focus
I am developing a vision os app for controlling an underwater ROV. I have ornaments with telemetry and buttons around a central video view feed. I have custom buttons mappings, such as "A" for locking the depth of the drone. However, when I look at buttons or certain ornaments, my custom gamepad logic is kept from running. This means that when a SwiftUI Button gains focus on visionOS, pressing the controller’s A button triggers the system’s default “click” on that Button rather than my custom buttonA handler. Essentially, focus interception by the system is stealing my A-press events and preventing my custom gamepad logic from running. Is there a way to disable the built in gamepad interaction and only allow my custom gamepad mappings?
1
0
99
Apr ’25
VoiceOver Not Scrolling to Focused TableView Cell
I have a view dynamically overlaid on a UITableView with proper padding (added when certain conditions are met). When VoiceOver focuses on a cell beneath this overlay, the focused element does not scroll into view. I’ve noticed similar behavior in Apple’s first-party Podcasts app. Please find the attached image for reference. How can I resolve this issue and ensure VoiceOver scrolls the focused cell into view?
1
0
64
Apr ’25
VoiceOver Text Recognition Announcing Hidden Labels
I have a UIImageView as the background of a custom UIView subclass. The image itself does not contain any text. On top of this image view, I have added two UILabels. To improve accessibility, I converted the entire view into a single accessibility element and set a proper accessibilityLabel. Additionally, I disabled accessibility for the UIImageView and the labels by setting isAccessibilityElement = false. However, when VoiceOver's Accessibility Recognition's Text Recognition feature is enabled, VoiceOver still detects and announces the text inside the UILabels at the end after reading my custom accessibility properties. This text should not be announced. It seems that VoiceOver treats the UILabel content as part of the UIImageView. Additionally, when using the Explore Image rotor action, the entire subview is recognized as a single image. Is this the expected behavior? If so, is there a way to disable VoiceOver’s text recognition for this view while keeping custom accessibility intact? class BackgroundLabelView: UIView { private let backgroundImageView = UIImageView() private let backgroundImageView2 = UIImageView() private let titleLabel = UILabel() private let subtitleLabel = UILabel() override init(frame: CGRect) { super.init(frame: frame) setupView() } required init?(coder: NSCoder) { super.init(coder: coder) setupView() configureAceesibility() } private func configureAceesibility() { backgroundImageView.isAccessibilityElement = false backgroundImageView2.isAccessibilityElement = false titleLabel.isAccessibilityElement = false subtitleLabel.isAccessibilityElement = false isAccessibilityElement = true accessibilityTraits = .button } func configure(backgroundImage: UIImage?, title: String, subtitle: String) { backgroundImageView.image = backgroundImage titleLabel.text = title subtitleLabel.text = subtitle accessibilityLabel = "Holiday Offer ," + title + "," + subtitle } private func setupView() { backgroundImageView2.contentMode = .scaleAspectFill backgroundImageView2.clipsToBounds = true backgroundImageView2.translatesAutoresizingMaskIntoConstraints = false backgroundImageView2.image = UIImage(resource: .bannerfestival) addSubview(backgroundImageView2) backgroundImageView.contentMode = .scaleAspectFit backgroundImageView.clipsToBounds = true backgroundImageView.translatesAutoresizingMaskIntoConstraints = false addSubview(backgroundImageView) titleLabel.font = UIFont.systemFont(ofSize: 18, weight: .bold) titleLabel.textColor = .white titleLabel.translatesAutoresizingMaskIntoConstraints = false titleLabel.numberOfLines = 0 addSubview(titleLabel) subtitleLabel.font = UIFont.systemFont(ofSize: 14, weight: .regular) subtitleLabel.textColor = .white.withAlphaComponent(0.8) subtitleLabel.translatesAutoresizingMaskIntoConstraints = false subtitleLabel.numberOfLines = 0 addSubview(subtitleLabel) NSLayoutConstraint.activate([ backgroundImageView2.leadingAnchor.constraint(equalTo: leadingAnchor), backgroundImageView2.trailingAnchor.constraint(equalTo: trailingAnchor), backgroundImageView2.heightAnchor.constraint(equalToConstant: 200), backgroundImageView.centerYAnchor.constraint(equalTo: centerYAnchor), backgroundImageView.topAnchor.constraint(equalTo: topAnchor), backgroundImageView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor), backgroundImageView.trailingAnchor.constraint(equalTo: trailingAnchor), backgroundImageView.bottomAnchor.constraint(equalTo: bottomAnchor), titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), titleLabel.trailingAnchor.constraint(lessThanOrEqualTo: centerXAnchor), titleLabel.bottomAnchor.constraint(equalTo: centerYAnchor, constant: -4), subtitleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), subtitleLabel.trailingAnchor.constraint(lessThanOrEqualTo: centerXAnchor), subtitleLabel.topAnchor.constraint(equalTo: centerYAnchor, constant: 4) ]) } override func layoutSubviews() { super.layoutSubviews() backgroundImageView.layer.cornerRadius = layer.cornerRadius } }
2
0
74
Apr ’25
accessibilityActivationPoint Not Working When Set Directly on UITableViewCell
I’m trying to set the accessibilityActivationPoint directly on a UITableViewCell so that VoiceOver activate on a specific button inside the cell. However, this approach doesn’t seem to work. Instead, when I override the accessibilityActivationPoint property inside the UITableViewCell subclass and return the desired point, it works as expected. Why doesn’t setting accessibilityActivationPoint directly on the cell work, but overriding it inside the cell does? Is there a recommended approach for handling this scenario? The following approach works, override var accessibilityActivationPoint: CGPoint { get { return convert(toggleSwitch.center, to: nil) } set{ super.accessibilityActivationPoint = newValue } } but setting accessibility point directly not works private func configureAccessibility() { isAccessibilityElement = true accessibilityLabel = titleLabel.text accessibilityTraits = .toggleButton accessibilityActivationPoint = self.convert(toggleSwitch.center, to: self) accessibilityValue = toggleSwitch.accessibilityValue }
2
0
87
Apr ’25
accessibilityElements excludes the unlisted subviews – How to Fix?
I have a parent view containing 10 subviews. To control the VoiceOver navigation order, I set only a few elements in accessibilityElements. However, the remaining elements are not being focused or are completely inaccessible. Is this the expected behavior? If I only specify a subset of elements in accessibilityElements, does it exclude the rest? What’s the best way to ensure all elements remain accessible while customising the order?
3
0
99
Apr ’25
Connections application with 4,000 pre-sign ups rejected unfairly - 4.3
For the last 2 years, our team at Panda has had one goal in mind: to change the failing connection application industry. The business model is severely flawed - evidenced in decline of users in match group etc (all public info). We are building the only connections app in the market without paid features – "We Don't Play Games”. This in itself revolutionizes a space which currently commodifies human connection; true connections aren’t forged through super-likes, platinum memberships and such pay-to-win models, where users that don’t pay are unfairly disadvantaged. Key Differentiators: Never having paid features 50/50 Male-Female Ratio: Our app will ensure a balanced male-to-female ratio, something not found in other apps, especially in countries like India, where dating apps are dominated by men. This helps create a healthier, more equitable user experience for all genders. In a country like India, how can any connections app succeed with 99.9% men and 0.1% women? Panda Duos: A first-of-its-kind feature where two sets of best friends can match with each other – an industry-first that no other major connections app offers. These elements, along with the app's core ethos, make Panda unique in an otherwise saturated market. The traditional models used by Match Group/Bumble are failing, as shown in their earnings reports, because they rely on a pay-to-win approach that doesn't deliver real value. Given these unique aspects, having received 4,550+ pre sign-ups, and our backing by a top VC, we strongly believe that Panda will offer an entirely different experience to users and remake a failing industry. This is not what Apple stands for, goes against fairness, and undermines the trust and respect that it should have as the only app store for iOS phones.
3
0
78
Mar ’25
Assistive Access Bugs
Hi! I have noticed a few glitches as well as some overall unfortunate cons with the assistive access mode. Alarms, timers, stopwatch, etc. do not sound or alert. However, I have an infant monitor app and I do get that sound alert so I know it is possible.. do I need to download a separate alarm app for it to work? Cannot make FaceTime calls with favorite contacts. Find My iPhone cannot jump to the maps app. Camera cannot zoom in or out. Photos cannot be deleted, edited, or shared in a shared album in the photos app. Photos/videos cannot be sent in messages. Spotify cannot be accessed from the lock screen. Apps do not stay open if you lock the phone screen or leave it on too long without touching the screen (auto locks). There is no flashlight option. I downloaded an app to have this feature but without being touched the screen will lock which shuts off the flashlight feature in the app until I unlock the phone again.
1
0
68
Mar ’25
The host app appears in Accessibility Permission
I'm learning XPC by inspecting the GitHub Copilot project. I figured out that the schema works as follows: The host app with a UI to manage settings A Service Extension that controls the Xcode Editor A communication bridge cli app that connects the first two As far as I understand an app appears in the Accessibility Permission when it calls the next method: let key = kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString AXIsProcessTrustedWithOptions([key: true] as CFDictionary) This method is only called by the Service Extension. However, when I run a release build from the /Application folder (where launch agents point to), there are two records appearing in the Accessibility Permission list: The host app The needed Service Extension I compared all metadata files from Copilot with my copy line-by-line, but still can't figure out why the host app record appears in the Accessibility Permission, since the host app does not call the AXIsProcessTrustedWithOptions() method at all. Could you give me any clue to help me wrap my head around it?
2
0
59
Mar ’25
Accessibility Issue - Date Picker Colour Contrast
In SwiftUI, the date picker component is breaking in colour contrast accessibility. Below code has been use to create date picker: struct ContentView: View { @State private var date = Date() @State private var selectedDate: Date = .init() var body: some View { let min = Calendar.current.date(byAdding: .day, value: 14, to: Date()) ?? Date() let max = Calendar.current.date(byAdding: .year, value: 4, to: Date()) ?? Date() DatePicker( "Start Date", selection: $date, in: min ... max, displayedComponents: [.date] ) .datePickerStyle(.graphical) .frame(alignment: .topLeading) .onAppear { selectedDate = Calendar.current.date(byAdding: .day, value: 14, to: Date()) ?? Date() } } } #Preview { ContentView() } attaching the screenshot of failure accessibility.
1
0
103
Mar ’25
Unable to Add Accessibility Trait to UISegmentedControl
I’m trying to add the .header accessibility trait to a UISegmentedControl so that VoiceOver recognizes it accordingly. However, setting the trait using the following code doesn’t seem to have any effect: segmentControl.accessibilityTraits = segmentControl.accessibilityTraits.union(.header) Even after applying this, VoiceOver doesn’t announce it as a header. Is there any workaround or recommended approach to achieve this?
1
0
170
Mar ’25
FocusState Issue in iOS 18 with Keyboard Navigation
I have implemented a SwiftUI view containing a grid of TextField elements, where focus moves automatically to the next field upon input. This behavior works well on iOS 16 and 17, maintaining proper focus highlighting when keyboard full access is enabled. However, in iOS 18 and above, the keyboard full access focus behaves differently. It always stays behind the actual focus state, causing a mismatch between the visually highlighted field and the active text input. This leads to usability issues, especially for users navigating with an external keyboard. Below is the SwiftUI code for reference: struct AutoFocusGridTextFieldsView: View { private let fieldCount: Int private let columns: Int @State private var textFields: [String] @FocusState private var focusedField: Int? init(fieldCount: Int = 17, columns: Int = 5) { self.fieldCount = fieldCount self.columns = columns _textFields = State(initialValue: Array(repeating: "", count: fieldCount)) } var body: some View { let rows = (fieldCount / columns) + (fieldCount % columns == 0 ? 0 : 1) VStack(spacing: 10) { ForEach(0..<rows, id: \.self) { row in HStack(spacing: 10) { ForEach(0..<columns, id: \.self) { col in let index = row * columns + col if index < fieldCount { TextField("", text: $textFields[index]) .frame(width: 40, height: 40) .multilineTextAlignment(.center) .textFieldStyle(RoundedBorderTextFieldStyle()) .focused($focusedField, equals: index) .onChange(of: textFields[index]) { newValue in if newValue.count > 1 { textFields[index] = String(newValue.prefix(1)) } if !textFields[index].isEmpty { moveToNextField(from: index) } } } } } } } .padding() .onAppear { focusedField = 0 } } private func moveToNextField(from index: Int) { if index + 1 < fieldCount { focusedField = index + 1 } } } struct AutoFocusGridTextFieldsView_Previews: PreviewProvider { static var previews: some View { AutoFocusGridTextFieldsView(fieldCount: 10, columns: 5) } } Has anyone else encountered this issue with FocusState in iOS 18? I really do believe that this is a bug strictly connected to keyboard navigation since I experienced similar problem also on UIKit equivalent of the view. Any insights or suggestions would be greatly appreciated!
1
0
471
Mar ’25