viewDidLayoutSubviews being called many times on orientation change in UIViewControllerRepresentable

I'm trying to implement a zoomable image in SwiftUI to display in a page view like the iOS photos app. I'm using UIViewControllerRepresentable to wrap a controller containing a UIScrollView to achieve this, and I'm running into a strange problem with the viewDidLayoutSubviews method being called way to many times when the device rotates. As far as I can tell, this is the cause of some animation problems I'm having with the scroll view.

After some experimentation I found a minimal reproducible example that happens to be extremely minimal:

class ViewController: UIViewController {
    override func viewDidLayoutSubviews() {
        print("viewDidLayoutSubviews: \(self.view.bounds)")
    }
}

struct Representable: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> ViewController {
        return ViewController()
    }

    func updateUIViewController(_ uiViewController: ViewController, context: Context) {
        
    }
}

struct ContentView: View {
    var body: some View {
        Representable()
    }
}

Launching the app and rotating the device once results in viewDidLayoutSubviews being called over 30 times. Interestingly, based on the values being printed, it seems that the bounds of the view are changing as the rotation animation happens.

Testing the same code in a fully UIKit application results in expected output:

viewDidLayoutSubviews: (0.0, 0.0, 393.0, 852.0)
viewDidLayoutSubviews: (0.0, 0.0, 852.0, 393.0)

viewDidLayoutSubviews is called once before and once after the orientation change.

Also worth noting, the problem is much less severe on iOS 17 (previous tests have been on iOS 16). viewDidLayoutSubviews is called more than expected (5 times), but not enough to break anything, and my zoomable image view works fine on iOS 17.

So is this just a bug with SwiftUI on iOS 16? Are there any workarounds? Unfortunately I can't just develop on iOS 17 for now, since it comes with its own collection of SwiftUI bugs that affect my code.

viewDidLayoutSubviews being called many times on orientation change in UIViewControllerRepresentable
 
 
Q