Search code examples
macosswiftuiswiftui-navigationsplitview

Saving the current width of a NavigationSplitView sidebar in SwiftUI


I'm making a macOS app in SwiftUI with the new NavigationSplitView. If a user resizes the sidebar, I'd like that new width to be remembered and restored when the app next loads.

A preference can be read in like so...

@State private var width = UserDefaults.standard.float(forKey: "sidebarWidth")
...
NavigationSplitView {
...
}.navigationSplitViewColumnWidth(ideal: width)

But this isn't a binding, so the width isn't updated when it changes.

Is it possible to save the current sidebar width when it changes (or when the app closes), so that it might later be restored?

Many thanks!


Solution

  • This is a function to retrieve the width:

    extension View {
        @ViewBuilder func onWidthChange(_ action: @escaping (CGFloat) -> Void) -> some View {
            self
                .background(
                    GeometryReader { reader in
                        Color.clear
                            .onChange(of: reader.frame(in: .global).width) { newValue in
                                action(newValue)
                            }
                    }
                )
        }
    }
    

    Usage:

    Text("Hi")
        .onWidthChange { newWidth in
            //save width
        }