SwiftUI - AppStorage 不适用于 GeometryReader

mal*_*low 5 ios swift swiftui geometryreader appstorage

这是一个简单的例子。您可以创建新的 SwiftUI iOS 项目并将其复制到 ContentView 文件。

import SwiftUI

struct Settings {
    static let onOff = "onOff"
}

struct ContentView: View {
    @AppStorage(wrappedValue: false, Settings.onOff) var onOff
    
    var body: some View {
        NavigationView {
            GeometryReader { reader in // < Comment out this line
                List {
                    Section (header:
                                VStack {
                                    HStack {
                                        Spacer()
                                        VStack {
                                            Text("THIS SHOULD BE FULL-WIDTH")
                                            Text("It is thanks to GeometryReader")
                                        }
                                        Spacer()
                                    }
                                    .padding()
                                    .background(Color.yellow)
                                    
                                    HStack {
                                        Text("This should update from AppStorage: ")
                                        Spacer()
                                        Text(onOff == true ? "ON" : "OFF")
                                    }
                                    .padding()
                                }
                                .frame(width: reader.size.width) // < Comment out this line
                                .textCase(nil)
                                .font(.body)
                    ) {
                        Toggle(isOn: $onOff) {
                            Text("ON / OFF")
                        }
                    }
                    
                }
                .listStyle(GroupedListStyle())
            } // < Comment out this line
            
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Run Code Online (Sandbox Code Playgroud)

我有3个要素:

  1. 黄色背景的文本 - 我需要它的全角,我使用 GeometryReader 来做到这一点。
  2. 文本。最后一个字应根据切换值切换开/关。这仅用于测试目的,以检查 AppStorage 是否正常工作。
  3. 切换 - 切换 onOff 变量并将其保存到 AppStorage (UserDefaults)。

AppStorage 仅在没有 GeometryReader 的情况下才能完美运行。请注释掉 3 个标记行来查看。

这是一个错误吗?或者我的 AppStorage 代码有问题?或者 GeometryReader 部分可能是错误的?如果我可以将黄色部分设置为全角,我就可以完全放弃 GeometryReader。

rob*_*off 5

在我的测试中有效的一种解决方案是提取 的GeometryReader内容,包括@AppStorage

struct ContentView: View {
    var body: some View {
        NavigationView {
            GeometryReader { proxy in
                _ContentView(width: proxy.size.width)
            }
        }
    }
}

struct _ContentView: View {
    var width: CGFloat
    @AppStorage(wrappedValue: false, Settings.onOff) var onOff

    var body: some View {
        List {
            Section(header: header) {
                Toggle(isOn: $onOff) {
                    Text("ON / OFF")
                }
            }

        }
        .listStyle(GroupedListStyle())
    }

    var header: some View {
        VStack {
            VStack {
                Text("THIS SHOULD BE FULL-WIDTH")
                Text("It is thanks to GeometryReader")
            }
            .padding()
            .frame(width: width)
            .background(Color.yellow)

            HStack {
                Text("This should update from AppStorage: ")
                Spacer()
                Text(onOff == true ? "ON" : "OFF")
            }
            .padding()
        }
        .textCase(nil)
        .font(.body)
    }
}
Run Code Online (Sandbox Code Playgroud)