I'm looking for a reliable way to detect when the UIScreen
of a UIView
changes.
I'm developing a renderer SDK that provides a custom UIView
subclass which performs OpenGL / Metal rendering, driven by a CADisplayLink
. To support scenarios like screen mirroring or external displays on iPad, I need to ensure the CADisplayLink
is created using the correct UIScreen
, so the refresh rate is accurate.
Ideally, I’d like a way to be notified in the view itself (without requiring scene delegate integration) whenever self.window.windowScene.screen
changes, even if trait values remain the same.
Any ideas or workarounds that work safely in production would be hugely appreciated!
Since iOS 13, the architecture is:
- The app can have multiple
UIScene
instances (typicallyUIWindowScene
). - Each
UIWindowScene
can have multipleUIWindow
s. - Each
UIWindow
hosts a view hierarchy.
To determine the correct UIScreen
, I access self.window.windowScene.screen
. If any component in that key path changes (window
, windowScene
, or screen
), I need to detect it and react.
Here’s what I’ve tried so far:
-
Overriding
willMoveToWindow:
anddidMoveToWindow:
This allows me to detect changes towindow
, but ifwindowScene
(of the window) orscreen
(of the scene) changes directly, I get no notification. -
Overriding
traitCollectionDidChange:
This works if the screen change causes a difference in traits (e.g., a differentdisplayScale
), but fails if the old and new screens share the same traits (e.g., identical scale). -
Listening to
UIScene
-related notifications
Notifications likeUISceneDidDisconnectNotification
orUISceneWillEnterForegroundNotification
only indicate scene lifecycle events, not that a particular view or window has moved to a different screen. -
Using KVO to observe
self.window.windowScene.screen
I found WebKit does something similar, but in practice this causes crashes. The error message suggests that"windowScene"
is not KVO-compliant, and my experience confirms it's not safe in production. -
Apple's official guidance uses
UIWindowSceneDelegate
In this example, Apple shows how to update aCADisplayLink
in aUIWindowSceneDelegate
'swindowScene:didUpdateCoordinateSpace:interfaceOrientation:traitCollection:
.
However, as an SDK provider delivering just aUIView
, I don't have control over the host app'sUIWindowSceneDelegate
.