我正在做一个由 5 个带有单选按钮的选项组成的页面。当我们点击一个选项时,元素的颜色应该改变。我从 API 响应中获取这些选项。我正在使用 MVVM 模型。我附上下面的代码。
我所困扰的是,当我改变布尔值时,它没有改变!
查看型号代码
import Foundation
import Combine
class DCListViewModel: ObservableObject {
@Published var DCList = [DCViewModel]()
init() {
fetchDcs()
}
func fetchDcs() {
ARMServices().getAllDc { (dcArr) in
if let dcArr = dcArr {
for dc in dcArr{
self.DCList.append(DCViewModel(dc: dc, isSelected: false))
}
}
}
}
}
class DCViewModel {
var id = UUID()
var dcStruct: DC
var isSelected: Bool
init(dc: DC, isSelected: Bool) {
self.dcStruct = dc
self.isSelected = isSelected
}
var url: String {
return self.dcStruct.url ?? "empty URL"
}
var dc: String {
return self.dcStruct.dc ?? "empty dc name"
}
}
Run Code Online (Sandbox Code Playgroud)
查看页面代码
struct SelectTableView: View {
var body: some View {
NavigationView {
VStack {
DCListView(dcList: self.dcListVM.DCList)
.padding(.horizontal)
}
.navigationBarTitle("Select the Data Centre")
}
}
}
struct DCListView: View{
var dcList: [DCViewModel]
init(dcList: [DCViewModel]) {
self.dcList = dcList
}
var body: some View {
ForEach(self.dcList, id: \.id) { dc in
Button(action: {
print("Tapped")
dc.isSelected.toggle()
}){
ZStack {
RoundedRectangle(cornerRadius: 8)
.stroke(dc.isSelected ? Color.init("borderSelected"): Color.init("border"))
.frame(height: 56)
.foregroundColor(.clear)
HStack {
Text(dc.dc)
.font(.custom("Montserrat", size: 16))
.fontWeight(.medium)
.foregroundColor(dc.isSelected ? Color.init("borderSelected") : .white)
.padding()
Spacer()
ZStack {
Circle()
.stroke(dc.isSelected ? Color.init("borderSelected") : Color("circleBorder"))
.frame(width: 18, height: 18)
.padding()
Circle()
.frame(width: 10, height: 10)
.foregroundColor(dc.isSelected ? Color.init("borderSelected"): Color.clear)
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
改成。DCViewModelstruct
或者,如果您必须将其保留为 a class,请使其DCViewModel符合ObservableObject 并在每个 single 中保留单个引用View。(这意味着您应该将该行作为单个减去View)
@Published 是一个属性包装器,仅当设置了包装值时才发布更改消息。
值类型和引用类型之间的区别:当您更改保存值类型(结构)的变量时,它实际上已被设置为新值。但是,当您更改引用类型(类)的值时,指向该对象的变量不会更改。
DCViewModel这就是为什么,在您的情况下,当您向(值类型)添加新值时Array,您总是为该数组设置一个新值,因此@Published会生效。然而,包装的值为DCViewModel,它是一个类(引用类型)。当您更改DCViewModel的值时,包装值的 setter 将不会被调用,也@Published不会发布消息。