Dark mode not enabling/disabling when using window.overrideUserInterfaceStyle on iPad

3.7k views Asked by At

I have successfully implemented the dark mode toggle by calling window.overrideUserInterfaceStyle in my app. When running the app in real iPhone or simulator, the function works fine.

But when I run the same script in a iPad, only the view.overrideUserInterfaceStyle works. If I try to use window.overrideUserInterfaceStyle it does not update the trait collection (and neither call traitCollectionDidChange(_).

To change the style I am doing (style from white to dark):

UIApplication.shared.connectedScenes.forEach { (scene: UIScene) in
    (scene.delegate as? SceneDelegate)?.window?.overrideUserInterfaceStyle = .dark //Just this one works on iPhone.
}
UIApplication.shared.delegate?.window??.overrideUserInterfaceStyle = .dark //Force
UIWindow.appearance().overrideUserInterfaceStyle = .dark //Force

When the code is executed above, it should replace the color of all UIViews that are configured with UIColor for light and dark styles. Also call traitCollectionDidChange(_). But none of these actions are happening on the iPad simulator.

This code above only works on the iPhone real/simulator, it should work on the iPad simulator too. I don't have any iPad capable of dark style here.

Maybe it's a bug on the simulator?

I also tried to create a sample app and the style change works on iPad indeed, but since it's a clean project with no libraries it should work.

I am also trying to minimize my app, still not working so I am afraid if it's a library creating a conflict.

The problem also happens when using UIApplication setup instead of UIScene.

I am using Xcode 11.3 and Swift 5 with some Cocoapod libraries.

1

There are 1 answers

0
Pedro Paulo Amorim On BEST ANSWER

If you are using custom transition, I recommend you to set viewController.overrideUserInterfaceStyle = .unspecified after you finish the animation.

Like this:

if #available(iOS 13.0, *) {
    viewController.overrideUserInterfaceStyle = .dark
}

UIView.animate(withDuration: defaultAnimationDuration, delay: 0, animations: {
    //animate viewController
}, completion: { [weak self] _ in
    if #available(iOS 13.0, *) {
        viewController.overrideUserInterfaceStyle = .unspecified
    }
})

This will make your UIViewController follow the UIWindow user interface style after all.