0

Problem

I'm trying to start an UIViewRepresentable ScrollView with a given zoom and position.

I set the new zoom and new contentOffset in the makeUIView, but the setContentOffset call has no VISUAL effect and when zooming back out from the new zoom, the scrollview moves the content as if the setContentOffset had had effect.

What am I doing wrong?

Code

Below is the entire code for the UIViewRepresentable. I've marked the most relevant lines with a 'SEE HERE' comment.

import SwiftUI

struct ZoomableScrollView<Content: View>: UIViewRepresentable {
    @EnvironmentObject var drawingModel: DrawingModel
    private var content: Content
    let screenScale: CGFloat
    
    init(screenScale: CGFloat, @ViewBuilder content: () -> Content) {
        self.screenScale = screenScale
        self.content = content()
    }

    func makeUIView(context: Context) -> UIScrollView {
        // set up the UIScrollView
        let scrollView = UIScrollView()
        scrollView.delegate = context.coordinator  // for viewForZooming(in:)

        let fullPageZoomScale = 0.85 * screenScale // screenScale is a constant
        scrollView.maximumZoomScale = fullPageZoomScale * 10
        scrollView.minimumZoomScale = fullPageZoomScale
        scrollView.zoomScale = fullPageZoomScale
        scrollView.bouncesZoom = true
        scrollView.delaysContentTouches = false

        // 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)
        
        /// -------- SEE HERE These two lines does not work as intended
        scrollView.setZoomScale(0.5319657829374683, animated: false)
        scrollView.setContentOffset(CGPoint(x: 518.5, y: 330.0), animated: false)
        /// -----
        
        return scrollView
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(hostingController: UIHostingController(rootView: self.content),
                           userScrolledAction: drawingModel.userScrollAction,
                           userZoomedAction: drawingModel.userZoomAction)
    }

    func updateUIView(_ uiView: UIScrollView, context: Context) {
        // update the hosting controller's SwiftUI content
        context.coordinator.hostingController.rootView = self.content
        assert(context.coordinator.hostingController.view.superview == uiView)
    }

    /// MARK: - Coordinator
    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)
        }
    }
}
berrou
  • 11
  • 3

1 Answers1

0

should move into

func updateUIView(_ uiView: UIScrollView, context: Context)
cassie
  • 1