The Limitation
SwiftUI’s ImageRenderer lets you render any SwiftUI view into a UIImage or CGImage. It works well for pure SwiftUI views, but silently fails – producing a blank or incomplete image – when the view tree contains components backed by UIKit or AppKit. This includes several commonly used views:
List(wraps UITableView / NSTableView)ScrollView(wraps UIScrollView / NSScrollView)TextEditor(wraps UITextView / NSTextView)Map(wraps MKMapView)
There is no compiler warning or runtime error. The renderer simply does not capture those portions of the view hierarchy.
The Workaround
When I needed to export a list-like layout as an image, the solution was to replace List with a pure SwiftUI equivalent built from VStack and manual styling:
let exportView = VStack(spacing: 0) {
ForEach(items) { item in
HStack {
Text(item.name)
Spacer()
Text(item.value)
.foregroundStyle(.secondary)
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
if item.id != items.last?.id {
Divider()
}
}
}
.background(.white)
.frame(width: 390)
let renderer = ImageRenderer(content: exportView)
renderer.scale = UIScreen.main.scale
if let image = renderer.uiImage {
// Use the rendered image
}The VStack with ForEach replicates the visual structure of a List without relying on any UIKit-backed views. Adding dividers, padding, and a background produces a result that looks close enough to a standard list for export purposes.
Practical Advice
If you plan to use ImageRenderer in your app, design your exportable views with this constraint in mind from the start. Build them from basic SwiftUI primitives: stacks, text, shapes, and images. Avoid any view that you know wraps a platform-specific control. Testing the render output early saves the frustration of discovering blank regions later.
