2

I have an issue with @AppStorage and ScrollViewReader that seems like a bug.

My @AppStorage variable fontSize is supposed to adjust the text size inside a ScrollViewReader. However, when its value changes, it does not update the view.

When I remove ScrollViewReader or change @AppStorage to @State, it will update.

What's wrong and how can I fix it?

import SwiftUI
struct ContentView: View {
    @AppStorage("fontSize") var fontSize: Int = 12
    // @State var fontSize: Int = 12
    
    var body: some View {
        VStack {
            Text("Hello, bigger world!")
                .font(.system(size: CGFloat(fontSize)))
            ScrollViewReader { proxy in
                ScrollView {
                    Text("Hello, bigger world!")
                    // @AppStorage var inside ScrollViewReader does not update?
                        .font(.system(size: CGFloat(fontSize)))
                }
            }
            Button("toggle font size") {
                fontSize += 2
            }
            .keyboardShortcut("+")
            Text("\(fontSize)")
        }
        .padding()
        .fixedSize()
        .onAppear {
            DispatchQueue.main.async {
                fontSize = 12
            }
        }
    }
}

macOS 12.6.9, Xcode 14.2 (SDK macOS 13.1)

3
  • Something happened to AppStorage recently and it isn’t working as it should, you should report a bug. Commented Oct 11, 2023 at 13:07
  • I'm on Xcode 14.2. Reported the bug. Commented Oct 11, 2023 at 17:16
  • this may be related, you can add that report number with your report Commented Oct 11, 2023 at 17:27

1 Answer 1

3

I found my own solution, analogous to this solution for GeometryReader. I split the ScrollView to a separate view:

import SwiftUI
struct ContentView: View {
    @AppStorage("fontSize") var fontSize: Int = 12
    
    var body: some View {
        VStack {
            Text("Hello, bigger world!")
                .font(.system(size: CGFloat(fontSize)))
            ScrollViewReader { proxy in
                ScrollViewContainer(fontSize: $fontSize, proxy: proxy)
            }
            Button("toggle font size") {
                fontSize += 2
            }
            .keyboardShortcut("+")
            Text("\(fontSize)")
        }
        .padding()
        .fixedSize()
        .onAppear {
            DispatchQueue.main.async {
                fontSize = 12
            }
        }
    }
}

/// A Container view to make @AppStorage value binding work (SwiftUI bug)
struct ScrollViewContainer: View {
    @Binding var fontSize: Int
    var proxy: ScrollViewProxy
    
    var body: some View {
        ScrollView {
            Text("Hello, bigger world!")
                .font(.system(size: CGFloat(fontSize)))
        }
    }
}

Using proxy with .scrollTo(ID) in this new view also works, which is the whole point of having ScrollViewReader.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.