0

Im trying to snapshot a SwiftUI View, but when I update that view (the text for example) and I snapshot the View, the image I get back is from the default view (previous render of the View, not the updated one)

On this code example there is a TextView to be snapshotted, when tapped it changes/updates, then pressing the button should save the new updated View with the TextView changed, but instead it saves the old version.

Extension on View to snapshot View:

extension View {
    func snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self)
        let view = controller.view
        
        let targetSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        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)
        }
    }
}

ContentView with button to snapshot View:

struct ContentView: View {
    var view: some View = ScreenShot()
    
    var body: some View {
        VStack {
            view
            
            Button("Save Image") {
                let image = view.snapshot()
                UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
            }
        }
    }
}

View to be snapshotted and updated:

struct ScreenShot: View {
    @State var updateView = false
    
    var body: some View {
        Text("View to be snapshotted \(updateView ? "(Update)" : "")")
           .tapGesture {
               updateView.toggle()
           }
    }
}

This is the initial View: Initial View

This is the updated View: Updated View

This is the view that gets saved: Saved View

BlueStarXD
  • 73
  • 6

1 Answers1

0

Figured out that doing the snapshot from outside the view being snapshotted does not respond to the updates, tried calling the snapshot function from inside the 'Screenshot' view and it worked.

I believe that is the correct approach but also feel like there could be another way (?)

BlueStarXD
  • 73
  • 6