2023-08-30 Coordinator in preview

When you're using the Coordinator pattern in a SwiftUI project, you'll find yourself sometimes wanting to preview the initial start of a "flow" of screens. But that's quite a bit of work because inside the coordinator, some boilerplate code needs to be present, to wrap the SwiftUI view in a UIHostingController.

This bit of code is useful to plunk in the utilities folder of your project, and use in the preview section of your SwiftUI view.

    private class PreviewViewController: UIViewController {
        private let coordinator: NavigationControllerCoordinator
        init(coordinator: NavigationControllerCoordinator) {
            self.coordinator = coordinator
            super.init(nibName: nil, bundle: nil)
        }
        required init?(coder: NSCoder) {
            fatalError()
        }
        override func viewDidLoad() {
            guard let navigationController = self.navigationController as? NavigationController else {
                return
            }
            title = "Preview"
            var configuration = UIButton.Configuration.filled()
            configuration.title = "Start"
            self.view = UIButton(configuration: configuration, primaryAction: UIAction(handler: {_ in
                navigationController.present(self.coordinator.navigationController, animated: true)
                self.coordinator.start()
            }))
        }
    }
    struct PreviewCoordinator: UIViewControllerRepresentable {
        let coordinator: NavigationControllerCoordinator
        typealias UIViewControllerType = NavigationController
        func makeUIViewController(context: Context) -> NavigationController {
            let viewController = PreviewViewController(coordinator: coordinator)
            return NavigationController(rootViewController: viewController)
        }
        func updateUIViewController(_ uiViewController: NavigationController, context: Context) {}
    }

Use as follows;

    struct NetworkScanQRView_Previews: PreviewProvider {
        static var previews: some View {
            PreviewCoordinator(coordinator: NetworkScanQRCoordinator.mocked)
        }
    }