swift 结构中的@AppStorage

63lcw9qa  于 2023-08-02  发布在  Swift
关注(0)|答案(1)|浏览(132)

我真的被困在这了。我想做几个按钮,每个按钮都有独立的ifButtonDisabled状态。当用户单击该按钮时,该按钮将禁用。由于我希望我的应用在重新加载或刷新时记住按钮的状态,因此我使用了AppStorage。问题是,由于每个按钮都有独立的状态,AppStorage变量也应该不同。但由于self不可用,我无法为AppStorage变量指定动态名称。
还有,有没有更好的替代方案来实现相同的功能???

struct ButtonData {
    var id: UUID {
        return UUID()
    }
    let level: String
    let bgColor: String
    let image: String
    @AppStorage(level) var ifDisabled: Bool = false
}

字符串

xmd2e60i

xmd2e60i1#

我不知道为什么你会想要一个每次访问都会改变的id,但是如果你只是想初始化isDisabled,你可以写你自己的init,并在那里给_isDisabled分配一个AppStorage

struct ButtonData {
    let level: String
    let bgColor: String
    let image: String

    // note that nothing is passed to @AppStorage here
    // and this property is not initialised to anything - we'll do that in init
    @AppStorage var isDisabled: Bool
    
    init(level: String, bgColor: String, image: String) {
        self.level = level
        self.bgColor = bgColor
        self.image = image
        // this is where isDisabled is initialised to false,
        // and the AppStorage with the level as key is created.
        self._isDisabled = AppStorage(wrappedValue: false, level)
    }
}

字符串
也就是说,如果你想像这样使用它,你的视图将不会更新:

struct ContentView: View {
    @State var buttonData = ButtonData(level: "foo", bgColor: "bar", image: "baz")
    var body: some View {
        Text("Foo")
            .onTapGesture {
//                buttonData.isDisabled.toggle()
            }
        Button("Button") { ... }.disabled(buttonData.isDisabled)
    }
}


因为AppStorage有一个nonmutating setter,所以设置它不会导致视图中的buttonData发生变化,所以SwiftUI不知道你的视图需要更新。
所以如果你想让AppStorage更新视图,你需要直接把它放在一个View中。例如,您可以创建自己的按钮视图,它接受一个ButtonData,并相应地设置其禁用状态:

// ButtonData can simply be
struct ButtonData {
    let level: String
    let bgColor: String
    let image: String
}

struct MyButton: View {
    let data: ButtonData
    @AppStorage var isDisabled: Bool
    init(data: ButtonData) {
        self.data = data
        self._isDisabled = AppStorage(wrappedValue: false, data.level)
    }
    
    var body: some View {
        // perhaps also provide init parameters for the action...
        Button {
            ...
        } label: {
            Image(data.image)
        }
        .disabled(isDisabled)
    }
}


现在,每当superview更新AppStorage时,MyButton也会更新其禁用状态。

相关问题