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