I have tried more than a few ways to convert a view to an image in swift. The one that seems the simplest is Hacking With Swift's implementation. The problem is, it returns a blank image and a not in the console saying "[Snapshotting] View (view) drawing with afterScreenUpdates:YES inside CoreAnimation commit is not supported.
I have also tried getting an image from the current graphics context to no avail. I have put things in DispatchQueue.main.async
, no matter what I do, I still don't get an image of the view.
Here is my code:
The View
struct ShareView: View {
@Binding var weightEntries: [WeightEntry]
@ObservedObject var goal: Goal
var settings: Settings
@State var showingShareSheet = false
@Environment(\.dismiss) var dismiss
var body: some View {
...
.sheet(isPresented: $showingShareSheet) {
ShareSheetView(activityItems: [ShareProgressView(weightEntries: weightEntries, goal: goal, settings: settings).snapshot()])
}
}
}
The View Extension
extension View {
func snapshot() -> UIImage {
let controller = UIHostingController(rootView: self)
let view = controller.view
let targetSize = controller.view.intrinsicContentSize
view?.bounds = CGRect(origin: .zero, size: targetSize)
view?.backgroundColor = .clear
let renderer = UIGraphicsImageRenderer(size: targetSize)
return renderer.image { _ in
view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
}
}
}
The Share Sheet View
struct ShareSheetView: UIViewControllerRepresentable {
typealias Callback = (_ activityType: UIActivity.ActivityType?, _ completed: Bool, _ returnedItems: [Any]?, _ error: Error?) -> Void
let activityItems: [Any]
let applicationActivities: [UIActivity]? = nil
let excludedActivityTypes: [UIActivity.ActivityType]? = nil
let callback: Callback? = nil
func makeUIViewController(context: Context) -> UIActivityViewController {
let controller = UIActivityViewController(
activityItems: activityItems,
applicationActivities: applicationActivities)
controller.excludedActivityTypes = excludedActivityTypes
controller.completionWithItemsHandler = callback
return controller
}
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
// nothing to do here
}
}
Thank you so much for your help, I really appreciate this especially since I have been stuck on this for a long time now. Have a nice day :)