I am investigating Accessibility Inspector/XCTest audit results in a SwiftUI app (Target Keeper), without suppressing warnings. Environment: Xcode 27.1 (27A9275), iPadOS 27.0 Simulator, macOS 27.0.1. Debug and Release builds pass. The app uses scalable text and labeled controls.
Element Detection / native sheet
Main-screen Element Detection passes when the sheet is closed.
With a SwiftUI .sheet presented, the iPad audit reports “Potentially inaccessible text”; XCUIAccessibilityAuditIssue.element is nil. Exported Inspector HTML highlights background labels behind/outside the sheet, rather than a foreground control.
The separate, data-free SwiftUI application below reproduces the modal-only warning; it links no application modules or persistence.
Actual iPad Simulator VoiceOver testing using XCUIDevice.shared.voiceOverService passes forward/backward traversal of the real application's modal controls, without reaching the background labels. This is simulator evidence, not physical-device acceptance.
A trial explicit modal container/.isModal trait did not clear the audit and was reverted; no warnings are filtered.
Minimal independent app:
import SwiftUI
@main struct ModalRepro: App {
@State private var showing=false
private let names=["Vegetables","Protein","Fruit","Dairy","Grains","Healthy Fats"]
var body:some Scene {WindowGroup {
NavigationStack {
VStack(spacing:24) {
Button("Nutrition") {}.accessibilityLabel("Choose Page").accessibilityValue("Nutrition")
LazyVGrid(columns:[GridItem(.flexible()),GridItem(.flexible()),GridItem(.flexible())],spacing:40) {
ForEach(names,id:\.self) { name in
Button {} label: {
VStack(spacing:10) {
Circle().fill(.blue.opacity(0.3)).frame(width:250,height:250)
Text(name).font(.system(size:17)).accessibilityHidden(true)
}
}.buttonStyle(.plain).accessibilityLabel(name)
}
}
Button("Show modal") {showing=true}
}.padding(24).frame(maxWidth:.infinity,maxHeight:.infinity).background(Color.black)
}.preferredColorScheme(.dark)
.sheet(isPresented:$showing) {
NavigationStack {
VStack {Text("Foreground content");Button("Close") {showing=false}}
.frame(maxWidth:.infinity,maxHeight:.infinity).background(Color.black)
.navigationTitle("Modal flow")
}.preferredColorScheme(.dark)
}
}}
}In an Xcode UI-test target, launch this app, run try app.performAccessibilityAudit(for: [.elementDetection]), tap “Show modal”, then run the same audit again. The first passes and the second fails. No issue handler ignores failures.
Contrast / scrolling — separate unresolved finding
All four iPhone combined-audit configurations (portrait/landscape, normal/maximum Dynamic Type) pass in the tested picker state. However, iPad maximum-text combined audits and a separate scrolled iPhone maximum-text landscape contrast audit still fail; we are not calling these resolved.
In the scrolled iPhone case, XCTest identifies a count label whose frame is entirely above the visible results viewport. Inspector's exported HTML reports 1.37:1 using #252526 versus #000000; its marked screenshot rectangle overlaps the dark search/header area, not visible count text. Visible sampled labels instead have white or light foregrounds on opaque dark fills (e.g. #FFFFFF/#1C1C1E = 17.01:1; #98989F/#1C1C1E = 5.94:1). These are screenshot core-pixel measurements, not proof every warning is false. We compare ordinary text against 4.5:1 and interactive non-text against 3:1. iPad maximum-text warnings have not yet been matched to an exact visible color pair. Original failures and HTML exports are preserved privately.
Questions
Is Element Detection expected to inspect background elements behind a presented native SwiftUI sheet? Is this a known tool limitation/framework issue, or does the sample need different semantics?
What is the supported way to establish modal accessibility boundaries with SwiftUI sheets, and when should .isModal be added explicitly?
How should we distinguish a real contrast defect from clipping, occlusion, translucency, or sampling of an offscreen element? Which Inspector export fields/diagnostics should establish the actual sampled text/background pair?
What additional evidence/manual and physical-device tests does Apple recommend before qualifying accessibility when the minimal audit reproduction fails but actual VoiceOver modal focus behaves correctly? We are not asking to waive audits or declare full accessibility from a VoiceOver pass alone.
I read Apple's audit guidance and modal trait documentation:
https://developer.apple.com/documentation/accessibility/performing-accessibility-audits-for-your-app
https://developer.apple.com/documentation/swiftui/accessibilitytraits/ismodal
https://developer.apple.com/help/app-store-connect/manage-app-accessibility/sufficient-contrast-evaluation-criteria/
Related discussion https://developer.apple.com/forums/thread/823968 recommends Feedback for a different apparent Dynamic Type false positive; it does not answer these modal/contrast questions. A Feedback draft is prepared but not submitted, so I have no Feedback ID yet. No private data, identifiers, credentials, app containers or confidential application source are included.
0
0
57