-1

I know there are plenty of answers pointing to traitCollectionDidChange, but that is going to be called when the userInterfaceStyle of a view controller changes, and I would like to let the user select between System, Light and Dark mode, so I am overriding the userInterfaceStyle of my view controllers and going to the device's settings and turning dark/light mode on won't call traitCollectionDidChange. Is there some other way to handle this? Am I going about it wrong?

When the app starts I can check UIScreen.main.traitCollection.userInterfaceStyle, so if there would be some way to observe changes to this property or use a notification, that would do it. But again, maybe I'm approaching this wrong, so I would appreciate any suggestions.

CristianMoisei
  • 2,071
  • 2
  • 22
  • 28
  • 1
    Why does your app provide its own way to switch between light and dark mode? Why not honor the device's setting and be done? That would make your app work like the vast majority of apps and it makes your code a lot simpler. Is there something unique about your app where giving the user the ability to change the app's appearance separately from the device's appearance is a feature desired by most of your users? – HangarRash Aug 15 '23 at 21:52
  • 1
    "going to the device's settings and turning dark/light mode on won't call traitCollectionDidChange" Yes it will, for the topmost view. – matt Aug 15 '23 at 21:54
  • Hey @HangarRash, the most common option is actually to give users these 3 choices. Take a look at Spark, Trello, Craft, ChatGPT and many others. Even StackOverflow, a web app, offers 'Light' 'System Setting' and 'Dark'. The reason for this is to give users control. They may not like the light or dark design of a particular app, they may prefer to set it to a certain theme. – CristianMoisei Aug 16 '23 at 09:46
  • Thanks @matt, what does the topmost view mean? I have a UIViewController called Container that is the main view controller and holds a page view controller and a few other things. I have the app side by side with system settings (in Catalyst) and changing dark and light mode doesn't call traitCollectionDidChange in my Container VC. There is no other VC higher up than this. This VC has its trait overridden so its traits don't change when the system value changes, that's why I was saying I need a way to detect the system change. – CristianMoisei Aug 16 '23 at 09:55
  • 1
    Then make a higher level container vc that does not override, so it _does_ hear about trait collection changes! Or just detect them in the window. – matt Aug 16 '23 at 16:52
  • Thank you @matt, how could I detect them in the window, custom window class where I observe traitCollectionDidChange? – CristianMoisei Aug 17 '23 at 07:43
  • 1
    Certainly, why not? Although personally I would use a super container view controller, but it's totally up to you. – matt Aug 17 '23 at 17:34

1 Answers1

-1

You can actually use the following method, e.g. in your UIViewController to observe changes regarding the theme.

willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
ProtocolGuy
  • 144
  • 8
  • Thank you, but I'm afraid this doesn't get called either. So my root vc implements all the functions below, then if I go to system settings and change from dark to light, neither of them gets called, because this vc has its traits overridden so nothing changes as far as it's concerned. https://ibb.co/c2NVRym – CristianMoisei Aug 16 '23 at 09:59