iosswiftswiftui

SwiftUI onChange for the horiz/vert size classes?


I'm trying to build an ios app (in ios 14) that reacts to changes in the current size classes. Specifically, I have a data model that I want to set different values on based on the size classes of the view. I'm having the hardest time figuring out how to do this.

To be clear - I don't want to change something in the view based on size class. I want to change something in the data model, which, in my humble opinion, should not be "aware" of the view.

I'm trying to set an onChange handler in my root view in SwiftUI, but can't come up with the proper incantation such that a change in either of the size classes (horiz/vert) cause my onChange handler to fire.

In other words, I'm trying to run arbitrary code when the size class changes.

If that makes sense to any of the far-more-talented ios developers on SO, please let me know. If there is any more information I can provide, please ask.

Thanks so much!


Solution

  • You can run code by using onChange for the horizontal or vertical size classes and get your model to run the code or change variables, etc.

    This View reports back to the model that the horizontal size has changed.

    struct MyView: View {
        @EnvironmentObject private var model:MyObservedObject
        @Environment(\.horizontalSizeClass) private var horizontalSizeClass
        
        var body: some View {
            HStack(alignment: .center) {
                Text("My view")
            }
            .onChange(of: horizontalSizeClass)  {
                model.somethingDidChange(for horizontalSizeClass)
            }
        }
    }
    

    The model runs the code.

    class MyObservedObject: ObservableObject {
        
        func somethingDidChange(for size: UserInterfaceSizeClass) {
            // run some code here, like:
            if size == .regular {
                // do something
            } else {
                // do something else
            }
        }
    }