2

I'm testing an app on the beta and am hitting problems with external screens.

We are seeing black borders around the app, which we would previously have corrected by setting overscanCompensation to .none however in iOS 13 the setting doesn't have any effect at all.

We once saw an error which said that it should be set on the UIScene (which we're not using) but the error only appeared once in the debugger (frustratingly!)

Any thoughts?

sminton
  • 211
  • 2
  • 11
  • Debugger Error: [OverscanCompensation] Requesting to set overscan compensation when we do not have a window scene – sminton Jun 21 '19 at 14:55

2 Answers2

3

Option 1. Have you tried to delay setting the overscanCompensation? Like setting it couple milliseconds later?

Option 2. You might have to adopt the new UISceneDelegate API. To get it working on my side (without storyboards) this is what I had to do:

In SceneDelegate.swift:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }

    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = YourViewController(nibName: nil, bundle: nil)

    self.window = window
    window.makeKeyAndVisible()
}

And if you want to have different UIWindowSceneDelegate for device screen vs external screen, in your AppDelegate:

// MARK: - UISceneSession Lifecycle

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {

    let sceneConfigurationName: String
    let delegateClass: AnyClass
    if connectingSceneSession.role == UISceneSession.Role.windowExternalDisplay {
        sceneConfigurationName = "External Display Configuration"
        delegateClass = SceneExternalDelegate.classForCoder()
    } else {
        sceneConfigurationName = "Default Configuration"
        delegateClass = SceneDelegate.classForCoder()
    }

    let sceneConfiguration = UISceneConfiguration(name: sceneConfigurationName, sessionRole: connectingSceneSession.role)
    sceneConfiguration.delegateClass = delegateClass
    return sceneConfiguration
}

func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    // Called when the user discards a scene session.
}

Don't forget to set the delegateClass, that was the missing piece to get the external screen working for me.

And lastly, in your Info.plist you should register these UISceneConfigurations (and remove storyboard references if needed):

<key>UIApplicationSceneManifest</key>
    <dict>
        <key>UIApplicationSupportsMultipleScenes</key>
        <false/>
        <key>UISceneConfigurations</key>
        <dict>
            <key>UIWindowSceneSessionRoleApplication</key>
            <array>
                <dict>
                    <key>UISceneConfigurationName</key>
                    <string>Default Configuration</string>
                    <key>UISceneDelegateClassName</key>
                    <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                </dict>
                <dict>
                    <key>UISceneConfigurationName</key>
                    <string>External Display Configuration</string>
                    <key>UISceneDelegateClassName</key>
                    <string>$(PRODUCT_MODULE_NAME).SceneExternalDelegate</string>
                </dict>
            </array>
        </dict>
    </dict>
</dict>
Ludovic Landry
  • 11,606
  • 10
  • 48
  • 80
0

You are getting that debugger error because you are not on the main queue. All you need to do is wrap your secondary screen setup inside a DispatchQueue.main.async{}.

DispatchQueue.main.async {
    // Setup your UIScreen here
}

If you are responding to didConnectNotification, who knows which thread you are getting notified on.

stacconi
  • 101
  • 1
  • 4