On macOS SwiftUI.TimelineView() inside NSViewController is causing AutoLayout recalculations

I have a complex app that requires the main SwiftUI view of the app to be embedded inside an NSHostingView which is a subview of an NSViewController's view. Then this NSViewController is wrapped using NSViewControllerRepresentable to be presented using SwiftUI's Window. And if I have a TimelineView inside my SwiftUI view hierarchy, it causes constant recalculation of the layout.

Here's a simplified demo code:

@main
struct DogApp: App {
    private let dogViewController = DogViewController()

    var body: some Scene {
        Window("Dog", id: "main") {
            DogViewControllerUI()
        }
    }
}

private struct DogViewControllerUI: NSViewControllerRepresentable {
    let dogViewController = DogViewController ()

    func makeNSViewController(context: Context) -> NSViewController { dogViewController }

    func updateNSViewController(_ nsViewController: NSViewController, context: Context) {}

    func sizeThatFits(_ proposal: ProposedViewSize, nsViewController: NSViewController, context: Context) -> CGSize? {
        debugPrint("sizeThatFits", proposal)
        return nil
    }
}

public class DogViewController: NSViewController {
    public override func viewDidLoad() {
        super.viewDidLoad()

        let mainView = MainView()
        let hostingView = NSHostingView(rootView: mainView)

        view.addSubview(hostingView)

        hostingView.translatesAutoresizingMaskIntoConstraints = false
        hostingView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        hostingView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        hostingView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        hostingView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    }
}

struct MainView: View {
    var body: some View {
        VStack {
            TimelineView(.animation) { _ in
                Color.random
                    .frame(width: 100, height: 100)
            }
        }
    }
}

extension Color {
    static var random: Color {
        Color(
            red: .random(in: 0...1),
            green: .random(in: 0...1),
            blue: .random(in: 0...1)
        )
    }
}

When running it's printing out this repeatedly (multiple times a second).

"sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0))
"sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0))
"sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0))
"sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0))
"sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0))
"sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0))
"sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0))

If I run an equivalent code for an iPad, it only prints twice. If I comment out TimelineView on macOS, then it only prints out the above logs when resizing the app window.

The main reason this is an issue is that it's clearly causing dramatic degradation in performance. I was told to submit a bug report after I submitted TSI so a SwiftUI engineer could investigate it. Case-ID: 7461887. FB13810482. This was back in May but I received no response. LLMs are no help, and I've experimented with all sorts of workarounds. My last hope is this forum, maybe someone has an idea of what might be going on and why the recalculation is happening constantly on macOS.

Sorry for the delay, this is a great description of the issue for sure, to get this back into traction I would suggest to provide a project for all the code that shows the issue, easier for people to confirmed the issue.

Do you get the same results with just the relevant code in a small test project?

If so, please share a link to your test project. That'll help us better understand what's going on. If you're not familiar with preparing a test project, take a look at Creating a test project.

Also when you have that project I would suggest to update the FB13810482.

You can see the status of your feedback in Feedback Assistant. There, you can track if the report is still being investigated, has a potential identifiable fix, or has been resolved in another way. The status appears beside the label "Resolution." We're unable to share any updates on specific reports on the forums.

For more details on when you'll see updates to your report, please see What to expect after submission.

Albert Pascual
  Worldwide Developer Relations.

On macOS SwiftUI.TimelineView() inside NSViewController is causing AutoLayout recalculations
 
 
Q