Unleash the UIKit trait system

RSS for tag

Discuss the WWDC23 Session Unleash the UIKit trait system

View Session

Posts under wwdc2023-10057 tag

4 Posts
Sort by:
Post not yet marked as solved
3 Replies
796 Views
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
Posted
by RolfS.
Last updated
.
Post not yet marked as solved
1 Replies
853 Views
In iOS17, traitCollectionDidChange gets triggered twice on iOS17 devices/simulators, while on iOS<17 devices/simulators, it only gets triggered once. I was wondering if there was a reason for this. I'm currently investigating issues between portrait and landscape and UI/view controllers looking weird because of the rotation and trying to figure out what the issue is. I found this thread https://developer.apple.com/forums/thread/732069 which makes me think that code should still work, but looking for any feedback that could help. Thanks!!
Posted
by joemer123.
Last updated
.
Post marked as solved
1 Replies
1.8k Views
I believe when trait collections were first introduced, the values were unknown initially, so you could put code that accessed those values in traitCollectionDidChange because it always changed from unknown to known values. An iOS update changed this behavior to provide an estimated initial value, so traitCollectionDidChange would only get called if its value changed from its initial value. This required us to optimize for the trait collection in viewDidLoad for example to handle its initial value and handle changes in traitCollectionDidChange. In iOS 17, it’s stated if you access traits before the view is added to the hierarchy, the values won’t be up-to-date. It’s recommended to use viewIsAppearing instead of viewDidLoad and viewWillAppear. traitCollectionDidChange is still invoked but deprecated replaced with a new registration API to be informed when a value changes. My question is, will the code written using the previous approach still work when compiled with the iOS 17 SDK? Meaning, does the system still provide an estimated initial value and inform you if it changed upon getting added to the view hierarchy? Or is this a breaking change in behavior that will require us to rewrite our logic moving code that accesses the traitCollection from viewDidLoad to viewIsAppearing (and be really careful in doing so because this function is called every time the view appears not just once)? Are there any scenarios where the code written for iOS 16 would stop working once compiled for iOS 17 if you access trait values in viewDidLoad and handle changes in traitCollectionDidChange? I’m trying to understand if I can keep my existing code and use the new approach going forward or if I need to revisit existing code that utilizes trait collections. Thanks!
Posted
by Jordan.
Last updated
.
Post not yet marked as solved
1 Replies
530 Views
Hi, I have a question regarding the use of UITraitBridgedEnvironmentKey inside the example project of Backyard Birds. It seems to me that there isn't a reason to use that protocol because we are not synching the UIKit and SwiftUI keys. Moreover, inside the extension, we use that protocol only to get the UITraitCollection to identify if is a phone or tv. Here is the Backyard Birds code to better clarify: // File: PrefersTabNavigationEnvironmentKey struct PrefersTabNavigationEnvironmentKey: EnvironmentKey { static var defaultValue: Bool = false } extension EnvironmentValues { var prefersTabNavigation: Bool { get { self[PrefersTabNavigationEnvironmentKey.self] } set { self[PrefersTabNavigationEnvironmentKey.self] = newValue } } } #if os(iOS) extension PrefersTabNavigationEnvironmentKey: UITraitBridgedEnvironmentKey { static func read(from traitCollection: UITraitCollection) -> Bool { return traitCollection.userInterfaceIdiom == .phone || traitCollection.userInterfaceIdiom == .tv } static func write(to mutableTraits: inout UIMutableTraits, value: Bool) { // Do not write. } } #endif I think that the extension PrefersTabNavigationEnvironmentKey is useless because if I want to know the userInterfaceIdiom I can use the UIDevice.current.userInterfaceIdiom. Moreover the set method inside prefersTabNavigation is useless too because I will never write the prefersTabNavigation. I re-write the class in this way: struct PrefersTabNavigationEnvironmentKey: EnvironmentKey { static var defaultValue: Bool = false } extension EnvironmentValues { var prefersTabNavigation: Bool { get { UIDevice.current.userInterfaceIdiom == .phone || UIDevice.current.userInterfaceIdiom == .tv } //set { self[PrefersTabNavigationEnvironmentKey.self] = newValue } --> remove that } } Is it correct or I'm missing something? Thank you in advance
Posted
by marcolg97.
Last updated
.