SwiftUI 无法从 Class 方法更改颜色按钮

SwiftUI Can't Change Color Button from Class Method

我已经创建了一个 KetupatButton class,方法如下:

class KetupatButton {
var condition = false
@State var colorToShow = Color(UIColor(red: 183/255, green: 191/255, blue: 150/255, alpha: 100))

func colorChange() {
    if condition == false {
        colorToShow = Color(UIColor(red: 183/255, green: 191/255, blue: 150/255, alpha: 100))
    } else {
        colorToShow = Color(UIColor(red: 19/255, green: 58/255, blue: 27/255, alpha: 100))
    }
}

func createButton(size: CGFloat) -> some View {
    return AnyView(Button(action: {
        self.condition = !self.condition
        self.colorChange()
        print(self.colorToShow)
        print(self.condition)
    }, label: {
        Rectangle()
            .frame(width: size, height: size, alignment: .leading)
            .foregroundColor(colorToShow)
    }))
}

}

但是,当我从我的 ContentView 调用 class 并点击按钮时,按钮不会改变它的颜色。即使当我打印 colorToShow 变量时,它也发生了变化。但是按钮的 UI 颜色没有改变...

这是我的 ContentView

struct ContentView: View {
var button1 = KetupatButton()

var body: some View {
    button1.createButton(size: 200)
}

}

您应该遵循更结构化的方法:将您的视图模型(即您的 class)与视图分开。以下是一些要遵循的步骤:

  1. 如果可以避免,您的视图模型不应包含该视图。创建一个特定的视图来显示按钮,与逻辑分开。您的按钮可能如下所示:
struct ButtonView: View {
    
    // Receive the view model
    @ObservedObject var viewModel: KetupatButton
    let size: CGFloat
    
    var body: some View {
        Button {

            // Use this to animate the change
            withAnimation {

                // The condition will automatically change the color, see the view model code
                viewModel.condition.toggle()
            }
        } label: {
            Rectangle()
                .frame(width: size, height: size, alignment: .leading)
                .foregroundColor(viewModel.colorToShow)
        }
    }
}
  1. 您的视图模型应该是一个 Observable 对象。此外,触发 UI 变化的值应该是 @Published 变量。另外我还做了一个条件改变颜色自动改变的方法,这样就可以去掉colorChnage().
class KetupatButton: ObservableObject {
    
    // When this variable changes, it will change also the color.
    var condition = false {
        didSet {
            if condition {
                colorToShow = Color(UIColor(red: 19/255, green: 58/255, blue: 27/255, alpha: 100))
            } else {
                colorToShow = Color(UIColor(red: 183/255, green: 191/255, blue: 150/255, alpha: 100))
            }
        }
    }

    @Published var colorToShow = Color(UIColor(red: 183/255, green: 191/255, blue: 150/255, alpha: 100))
}
  1. 最后,ContentView 应该创建一个视图模型的实例作为 @StateObject 与子视图共享,就像我们上面创建的 ButtonView:
struct ContentView: View {
    @StateObject var viewModel = KetupatButton()

    var body: some View {
        ButtonView(viewModel: viewModel, size: 200)
    }
}

现在,您可以看到按钮的颜色发生了变化。