Turns out you need to listen for UIScreen.didConnectNotification and then make changes to UIWindow.
This is how I solved it.
You need to listen for the connect/disconnect notifications. These are triggered when a user does the whole screen share thing.
In have the following listeners on my root View inside WindowGroup in the main App file:
.onReceive(screenDidConnectPublisher, perform: screenDidConnect)
.onReceive(screenDidDisconnectPublisher, perform: screenDidDisconnect)
Here are the publishers:
private var screenDidConnectPublisher: AnyPublisher<UIScreen, Never> {
NotificationCenter.default
.publisher(for: UIScreen.didConnectNotification)
.compactMap { $0.object as? UIScreen }
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
}
private var screenDidDisconnectPublisher: AnyPublisher<UIScreen, Never> {
NotificationCenter.default
.publisher(for: UIScreen.didDisconnectNotification)
.compactMap { $0.object as? UIScreen }
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
}
The final parts are the functions that you run when the notification is received:
private func screenDidConnect(_ screen: UIScreen) {
let window = UIWindow(frame: screen.bounds)
window.windowScene = UIApplication.shared.connectedScenes
.first { ($0 as? UIWindowScene)?.screen == screen }
as? UIWindowScene
let view = ExternalView().environmentObject(externalDisplayContent)
let controller = UIHostingController(rootView: view)
window.rootViewController = controller
window.isHidden = false
additionalWindows.append(window)
externalDisplayContent.isShowingOnExternalDisplay = true
}
private func screenDidDisconnect(_ screen: UIScreen) {
additionalWindows.removeAll { $0.screen == screen }
externalDisplayContent.isShowingOnExternalDisplay = false
}
externalDisplayContent is just a custom struct I created that passes along the information I want to display on the ExternalView, which is just a regular SwiftUI view.
You can see that the content gets passed through as an environment object, but it doesn't have to. You can use an initialiser on the view instead if you prefer.
I think you may also get away with passing through bindings.