Cannot Convert SwiftUI view to UIImage

238 views Asked by At

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 :)

0

There are 0 answers