Environment:
iOS 16.0+
SwiftUI
Problem Description: I am using ImageRenderer to convert a SwiftUI view into a UIImage for sharing purposes. The view renders perfectly fine on-screen. However, in the generated UIImage, specific Text elements completely disappear.
After debugging, I found that the issue is caused by the @AccessibilityFocusState property wrapper. Any Text view that has the .accessibilityFocused(_:) modifier applied to it will be completely missing from the ImageRenderer output. Other views (like Text without the modifier, or Image views) in the exact same hierarchy render perfectly.
It seems that because ImageRenderer renders the view off-screen without a live accessibility environment/tree, the accessibility focus binding silently breaks the layout or rendering of that specific element.
Minimal Reproducible Example:
Here is a generic, drop-in example that demonstrates the bug. When you tap "Capture with ImageRenderer", the resulting image will only contain the subtitle, while the title text vanishes.
import SwiftUI
// 1. The View we want to render
struct ComponentView: View {
// The accessibility focus state causing the issue
@AccessibilityFocusState private var isTitleFocused: Bool
var body: some View {
VStack(spacing: 12) {
// BUG: This text will NOT appear in the rendered image
Text("Title (with accessibility focus)")
.font(.headline)
.accessibilityFocused($isTitleFocused)
// This text WILL appear normally
Text("Subtitle (no accessibility focus)")
.font(.subheadline)
}
.padding()
.background(Color.blue.opacity(0.1))
.cornerRadius(12)
}
}
// 2. The Container to test the rendering
struct ContentView: View {
@State private var renderedImage: UIImage?
var body: some View {
VStack(spacing: 40) {
// On-screen: Both Title and Subtitle appear perfectly
VStack {
Text("Live On-Screen View:")
.font(.caption)
ComponentView()
}
Button("Capture with ImageRenderer") {
renderImage()
}
.buttonStyle(.borderedProminent)
// Off-screen render: Title is missing!
if let image = renderedImage {
VStack {
Text("Rendered UIImage Result:")
.font(.caption)
Image(uiImage: image)
.overlay(
Rectangle().stroke(Color.red, style: StrokeStyle(lineWidth: 1, dash: [5]))
)
}
}
}
.padding()
}
@MainActor
private func renderImage() {
let renderer = ImageRenderer(content: ComponentView())
renderer.scale = UIScreen.main.scale
if let uiImage = renderer.uiImage {
self.renderedImage = uiImage
}
}
}
Questions:
Is this a known limitation of ImageRenderer not supporting the accessibility environment?
Is there a way to inject an accessibility environment into ImageRenderer so these modifiers don't break the render?
Are there any cleaner workarounds other than manually stripping accessibility modifiers before rendering?