Handling trait changes (for dark mode)

In an objective C app I'm now using (in every view controller):

  • (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection

{ ..... }

to handle dark mode changes. This is all very easy to implement.

traitCollectionDidChange is deprecated in iOS 17.

In the documentation there is no objective C example on how to work with the new iOS17 registerForTraitChanges function. Hard to figure out how to do this. Am not familiar with Swift, so the wwdc video could not help me.

Where can I find some objective C examples?

Best regards/Rolf Netherlands

Replies

Tried the following in Objective C:

UITraitUserInterfaceStyle* style = [[UITraitUserInterfaceStyle alloc] init];

NSArray* traits = [[NSArray alloc] initWithObjects: style, nil];

[self registerForTraitChanges:traits withTarget:self action:@selector(handleStyleChange)];

[traits release];
[style release];

Unfortunately, this crashes in registerForTraitChanges:

UIKitCore`-[UIViewController registerForTraitChanges:withTarget:action:]:

  0x1acce3f90 <+60>:  bl     0x1acf55568               ; +[UITraitCollection _traitTokensIncludingPlaceholdersForTraits:]

-> 0x1acce3f94 <+64>: bl 0x1afc953c0

The beta documentation isn’t super helpful on this (yet) but notice that the UITrait type is defined like this:

typedef Class<UITraitDefinition> UITrait API_AVAILABLE(ios(17.0), tvos(17.0), watchos(10.0));

So -registerForTraitChanges:withTarget:action: takes an array of Classes, not instances of those classes. You can make it like this:

NSArray<UITrait> *traits = @[UITraitUserInterfaceStyle.self];

Note that if you had declared your array type as NSArray<UITrait> * then the compiler would warn about the type error.

[traits release];
[style release];

Also, if you’re working on cleaning up deprecated code, I’d vote to start by converting your app to use ARC. Manual -release has been obsolete for many years.

Hi Scott,

Thank you very much for your input, it now works.

Did not know this notation: UITraitUserInterfaceStyle.self

It seems to be the same as UITraitUserInterfaceStyle.class which is perhaps a more intuitive notation? Anyway, both notations work, super!

I'm mainly programming in C and always a bit afraid that memory is freed behind the scenes. But will give ARC a serious try. Thanks for the suggestion.