'Start SwiftUI implementation of UIScrollView at specific scroll and zoom

I have some experience in SwiftUI, but am new to UIKit.

I'd like to import the zoom and position from one instance of an UIViewRepresentable UIKit ScrollView to another. So, basically, the user scrolls and zooms and later, in another branch of the view hierarchy, I want to start zoomed in at that zoom and position. I can't get it to work though, even after many attempts.

Below is my makeUIView function where I try to set the position and zoom that I want (after some initial setup).

   func makeUIView(context: Context) -> UIScrollView {
        // set up the UIScrollView
        let scrollView = UIScrollView()
        scrollView.delegate = context.coordinator
        scrollView.bouncesZoom = true
        scrollView.delaysContentTouches = false
        scrollView.maximumZoomScale = 0.85 * screenScale * 10
        scrollView.minimumZoomScale = 0.85 * screenScale
        
        // create a UIHostingController to hold our SwiftUI content
        let hostedView = context.coordinator.hostingController.view!
        hostedView.translatesAutoresizingMaskIntoConstraints = true
        hostedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        hostedView.frame = scrollView.bounds
        scrollView.addSubview(hostedView)
        
/*
 Here I add the zoom and position
*/
        scrollView.zoomScale = 0.85 * screenscale
        // add zoom and content offset
        if let zoomScale = zoomScale, let contentOffset = contentOffset {
            scrollView.contentOffset = contentOffset
            
            // make sure it is within the bounds
            var newZoomScale = zoomScale
            if zoomScale < scrollView.minimumZoomScale {
                print("too small")
                newZoomScale = scrollView.minimumZoomScale
            } else if zoomScale > scrollView.maximumZoomScale  {
                print("too large")
                newZoomScale = scrollView.maximumZoomScale
            }
            
            scrollView.setContentOffset(contentOffset, animated: true)
            scrollView.setZoomScale(newZoomScale, animated: true)
        }
        
        return scrollView
    }

The way I get the zoom and contentOffset in the first place is to grab the values from the Coordinator in first ScrollView instance using the below code. As far as I can tell this works well and I get updates with sensible values after zooming or scrolling. The first code snippet contains the makeCoordinator function where I initiate the coordinator with methods from an environmentObject (which then updates said object). The second snippet contains the Coordinator.

    func makeCoordinator() -> Coordinator {
        return Coordinator(hostingController: UIHostingController(rootView: self.content),
                           userScrolledAction: drawingModel.userScrollAction,
                           userZoomedAction: drawingModel.userZoomAction)
    }
    class Coordinator: NSObject, UIScrollViewDelegate {
        var hostingController: UIHostingController<Content>
        let userScrolledAction: (CGPoint) -> Void
        let userZoomedAction: (CGFloat) -> Void

        init(hostingController: UIHostingController<Content>, userScrolledAction: @escaping (CGPoint) -> Void, userZoomedAction: @escaping (CGFloat) -> Void) {
            self.hostingController = hostingController
            self.userScrolledAction = userScrolledAction
            self.userZoomedAction = userZoomedAction
        }

        func viewForZooming(in scrollView: UIScrollView) -> UIView? {
            return hostingController.view
        }

        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            userScrolledAction(scrollView.contentOffset)
        }

        func scrollViewDidZoom(_ scrollView: UIScrollView) {
            userZoomedAction(scrollView.zoomScale)
        }
    }


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source