I'm trying to render the SwiftUI View as an UIImage then let the user choose to save to the camera roll or send to others via email.
As an example, I want to render a list of 50 rows into a UIImage.
struct MyList: View {
var body: some View {
List {
ForEach(0 ..< 50, id:\.self) {
Text("row \($0)")
}
}
}
}
Searched over the internet for the past few weeks still with no luck. I have tried 2 different approaches.
1. UIHostingController (source here)
let hosting = UIHostingController(rootView: Text("TEST"))
hosting.view.frame = // Calculate the content size here //
let snapshot = hosting.view.snapshot // output: an empty snapshot of the size
print(hosting.view.subviews.count) // output: 0
I've tried layoutSubviews()
, setNeedsLayout()
, layoutIfNeeded()
, loadView()
, but all still resulted 0 subviews.
2. UIWindow.rootViewController (source here)
var vc = UIApplication.shared.windows[0].rootViewController
vc = vc.visibleController // loop through the view controller stack to find the top most view controller
let snapshot = vc.view.snapshot // output: a snapshot of the top most view controller
This almost yields the output I have wanted. However, the snapshot I get is literally a screenshot, i.e. with a Navigation bar, Tab bar and fixed size (same as screen size). What I need to capture is simply the view's content without those bars, and may sometimes be larger than the screen (my view is a long list in this example).
Tried to query vc.view.subviews
to look for the table view I want, but returning an unhelpful [<_TtGC7SwiftUI16PlatformViewHostGVS_42PlatformViewControllerRepresentableAdaptorGVS_16BridgedSplitViewVVS_22_VariadicView_Children7ElementGVS_5GroupGVS_19_ConditionalContentS4_GVS_17_UnaryViewAdaptorVS_9EmptyView______: 0x7fb061cc4770; frame = (0 0; 414 842); anchorPoint = (0, 0); tintColor = UIExtendedSRGBColorSpace 0 0.478431 1 1; layer = <CALayer: 0x600002d8caa0>>]
.
Any help is much appreciated.