制限事項
SwiftUIのImageRendererを使うと、任意のSwiftUIビューをUIImageやCGImageにレンダリングできます。純粋なSwiftUIビューでは問題なく動作しますが、UIKitやAppKitで実装されたコンポーネントがビューツリーに含まれている場合、サイレントに失敗し、空白または不完全な画像が生成されます。対象となるビューには以下が含まれます:
List(UITableView / NSTableViewをラップ)ScrollView(UIScrollView / NSScrollViewをラップ)TextEditor(UITextView / NSTextViewをラップ)Map(MKMapViewをラップ)
コンパイラの警告もランタイムエラーもありません。レンダラーはビュー階層のそれらの部分を単にキャプチャしないだけです。
回避策
リストのようなレイアウトを画像としてエクスポートする必要があった際の解決策は、ListをVStackと手動スタイリングで構築した純粋なSwiftUIの同等物に置き換えることでした:
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
}VStackとForEachによる構成は、UIKitベースのビューに依存することなくListの視覚的な構造を再現します。ディバイダー、パディング、背景を追加することで、エクスポート用途として標準的なリストに十分近い結果が得られます。
実践的なアドバイス
アプリでImageRendererを使用する予定がある場合は、この制約を最初から念頭に置いてエクスポート可能なビューを設計してください。基本的なSwiftUIプリミティブ(スタック、テキスト、シェイプ、イメージ)で構築し、プラットフォーム固有のコントロールをラップしているビューは避けてください。レンダリング出力を早い段階でテストしておくことで、後から空白の領域を発見するフラストレーションを回避できます。
