首页 > 解决方案 > 如何单独和整体同时控制视图

问题描述

所以我遇到了一个我从未遇到过的问题。下图中是包含许多视图(单个阿拉伯语块)的父视图。

在此处输入图像描述

当用户得到正确答案时,该块将变为灰色并禁用。这是通过让单个语言块拥有视图并更改该状态来实现的。@State private var isDisabled = false

但最终如果用户回答每一个,那么所有的块都会变成灰色。然后如何将所有单独拥有的视图 Bool 状态重置为 true?

我不能让父视图拥有 Bool,因为尽管这会将所有视图重置为正常状态,但当再次禁用单个视图时,只会禁用它们,当然这是不希望的。

如果需要,将发布一个工作示例。谢谢。

标签: swiftui

解决方案


有几种(很多?)不同的可能方法,但这里有一个:


class StateManager : ObservableObject {
    @Published var states = Array(repeating: false, count: 6)
    
    func reset() {
        states = states.map { _ in
            false
        }
    }
}

struct ContentView : View {
    @ObservedObject var vm = StateManager()
    
    var body: some View {
        VStack {
            Box(state: $vm.states[0])
            Box(state: $vm.states[1])
            Box(state: $vm.states[2])
            Box(state: $vm.states[3])
            Box(state: $vm.states[4])
            Box(state: $vm.states[5])
            
            Button(action: {
                vm.reset()
            }) {
                Text("Reset")
            }
        }
    }
}

struct Box : View {
    @Binding var state : Bool
    
    var body: some View {
        Button(action: {
            state.toggle()
        }) {
            Text(state ? "Disabled" : "Enabled")
        }
        .disabled(state)
    }
}

我正在使用一个 ObservedObject 来跟踪所有状态。当一个项目被点击时,它会在状态数组中的正确索引处发送它的值。

重置按钮只需将所有状态更改回 即可false

通过将您的状态保持在一个地方(ObservableObject),您有更多机会根据其他项目的状态改变状态,而不会遇到您遇到的问题,其中子视图只知道自己的状态并且不知道无法控制其他人。

此外,通过使用Array状态,您可以避免制作一堆重复的 @State 项目。请注意,Array也可能包含Boolean比值更复杂的东西——它可能是关于该对象状态的完整信息结构。

更新: ObservableObject 被传递的版本:


class StateManager : ObservableObject {
    @Published var states = Array(repeating: false, count: 6)
    
    func reset() {
        states = states.map { _ in
            false
        }
    }
}

struct ContentView : View {
    @ObservedObject var vm = StateManager()
    
    var body: some View {
        VStack {
            Box(index: 0, stateManager: vm)
            Box(index: 1, stateManager: vm)
            Box(index: 2, stateManager: vm)
            Box(index: 3, stateManager: vm)
            Box(index: 4, stateManager: vm)
            Box(index: 5, stateManager: vm)
            
            Button(action: {
                vm.reset()
            }) {
                Text("Reset")
            }
        }
    }
}

struct Box : View {
    var index : Int
    @ObservedObject var stateManager : StateManager
    
    var state : Bool {
        stateManager.states[index]
    }
    
    var body: some View {
        Button(action: {
            stateManager.states[index].toggle()
        }) {
            Text(state ? "Disabled" : "Enabled")
        }
        .disabled(state)
    }
}


推荐阅读