horizontalSizeClass returning nil

Viewed 519

I'm trying to make my swiftUI view resize dynamically. I see that the way to do this is to use the environment info like below:

@Environment(\.horizontalSizeClass) var sizeClass

However, it does not seem to return anything. When using the debugger, I see that the variable is set to 'nil'. What am I doing wrong? Do I need to enable an option or something in info.plist for example?

My code is pretty basic:

struct ContentView: View {

    @Environment(\.horizontalSizeClass) var sizeClass

    var body: some View {
        if self.sizeClass == .compact {
            Home_Vertical()
                
        }
        else {
            Home_Horizontal()
        }
    }
}

I'm developing for iPhone and allowed all device orientations. The iOS deployment target is iOS 14.0 and xCode's version is 12.3.

2 Answers

It is optional by interface declaration (see below), so it is "by design" - it means system might not detected yet size class, and it will be updated later. You should handle such case explicitly to whatever appropriate to your app.

extension EnvironmentValues {

    /// The horizontal size class of this environment.
    @available(macOS, unavailable)
    @available(tvOS, unavailable)
    @available(watchOS, unavailable)
    public var horizontalSizeClass: UserInterfaceSizeClass?

Size classes work differently than orientations.

For example, for iPhone 12 Pro you have two combinations:

  • when orientation: vertical -> verticalSizeClass: regular, horizontalSizeClass: compact
  • when orientation: horizontal -> verticalSizeClass: compact, horizontalSizeClass: compact

Which means that for most iPhones @Environment(\.horizontalSizeClass) var sizeClass will always be compact regardless of the orientation.

In general you should design your views against size classes and not device orientation.

However, if you really want to change views depending on the orientation you can subscribe to UIDevice.orientationDidChangeNotification as explained here:

Related