在列表中。变异运算符的左侧是不可变的:'item' 是一个 'let' 常量
In a List. Left side of mutating operator isn't mutable: 'item' is a 'let' constant
Xcode 12.代码和生命周期都是Swiftui
我看过其他人的相关问题,他们似乎只是将整个项目代码转储在这里;从中挑选我需要的东西有点不知所措。
因此,我已将问题分解为最简单的示例。
目标是在我按下 + 按钮时迭代 numberX。
提前致谢!
struct InfoData: Identifiable {
var id = UUID()
var nameX: String
var numberX: Int
}
class ContentX: ObservableObject {
@Published var infoX = [
InfoData(nameX: "Example", numberX: 1)
]
}
struct ContentView: View {
@StateObject var contentX = ContentX()
var body: some View {
List(contentX.infoX) { item in
HStack {
Text("\(item.nameX)")
Spacer()
Button("+") {
item.numberX += 1 //Eror shows up here <<
}
Text("\(item.numberX)")
}
}
}
}
在您使用的语法中,item
是一个不可变值,正如错误告诉您的那样。你不能改变它,因为它不代表与它来自的数组的真正连接——它只是在 List
迭代中使用的临时可读副本。
如果您可以升级到 Xcode 13,您可以访问 List
和 ForEach
中称为元素绑定语法的东西,让您可以这样做:
struct ContentView: View {
@StateObject var contentX = ContentX()
var body: some View {
List($contentX.infoX) { $item in //<-- Here
HStack {
Text("\(item.nameX)")
Spacer()
Button("+") {
item.numberX += 1
}
Text("\(item.numberX)")
}
}
}
}
这为您提供了可变的 Binding
到 item
,允许您更改其值并将它们反映在原始数组中。
在 Xcode 13/Swift 5.5 之前,您必须定义自己的方式来更改数组中的元素。这是一个解决方案:
class ContentX: ObservableObject {
@Published var infoX = [
InfoData(nameX: "Example", numberX: 1)
]
func alterItem(item: InfoData) {
self.infoX = self.infoX.map { [=11=].id == item.id ? item : [=11=] }
}
}
struct ContentView: View {
@StateObject var contentX = ContentX()
var body: some View {
List(contentX.infoX) { item in
HStack {
Text("\(item.nameX)")
Spacer()
Button("+") {
var newItem = item
newItem.numberX += 1
contentX.alterItem(item: newItem)
}
Text("\(item.numberX)")
}
}
}
}
或者,使用自定义 Binding
的另一个选项:
class ContentX: ObservableObject {
@Published var infoX = [
InfoData(nameX: "Example", numberX: 1)
]
func bindingForItem(item: InfoData) -> Binding<InfoData> {
.init {
self.infoX.first { [=12=].id == item.id }!
} set: { newValue in
self.infoX = self.infoX.map { [=12=].id == item.id ? newValue : [=12=] }
}
}
}
struct ContentView: View {
@StateObject var contentX = ContentX()
var body: some View {
List(contentX.infoX) { item in
HStack {
Text("\(item.nameX)")
Spacer()
Button("+") {
contentX.bindingForItem(item: item).wrappedValue.numberX += 1
}
Text("\(item.numberX)")
}
}
}
}
Xcode 12.代码和生命周期都是Swiftui
我看过其他人的相关问题,他们似乎只是将整个项目代码转储在这里;从中挑选我需要的东西有点不知所措。 因此,我已将问题分解为最简单的示例。
目标是在我按下 + 按钮时迭代 numberX。
提前致谢!
struct InfoData: Identifiable {
var id = UUID()
var nameX: String
var numberX: Int
}
class ContentX: ObservableObject {
@Published var infoX = [
InfoData(nameX: "Example", numberX: 1)
]
}
struct ContentView: View {
@StateObject var contentX = ContentX()
var body: some View {
List(contentX.infoX) { item in
HStack {
Text("\(item.nameX)")
Spacer()
Button("+") {
item.numberX += 1 //Eror shows up here <<
}
Text("\(item.numberX)")
}
}
}
}
在您使用的语法中,item
是一个不可变值,正如错误告诉您的那样。你不能改变它,因为它不代表与它来自的数组的真正连接——它只是在 List
迭代中使用的临时可读副本。
如果您可以升级到 Xcode 13,您可以访问 List
和 ForEach
中称为元素绑定语法的东西,让您可以这样做:
struct ContentView: View {
@StateObject var contentX = ContentX()
var body: some View {
List($contentX.infoX) { $item in //<-- Here
HStack {
Text("\(item.nameX)")
Spacer()
Button("+") {
item.numberX += 1
}
Text("\(item.numberX)")
}
}
}
}
这为您提供了可变的 Binding
到 item
,允许您更改其值并将它们反映在原始数组中。
在 Xcode 13/Swift 5.5 之前,您必须定义自己的方式来更改数组中的元素。这是一个解决方案:
class ContentX: ObservableObject {
@Published var infoX = [
InfoData(nameX: "Example", numberX: 1)
]
func alterItem(item: InfoData) {
self.infoX = self.infoX.map { [=11=].id == item.id ? item : [=11=] }
}
}
struct ContentView: View {
@StateObject var contentX = ContentX()
var body: some View {
List(contentX.infoX) { item in
HStack {
Text("\(item.nameX)")
Spacer()
Button("+") {
var newItem = item
newItem.numberX += 1
contentX.alterItem(item: newItem)
}
Text("\(item.numberX)")
}
}
}
}
或者,使用自定义 Binding
的另一个选项:
class ContentX: ObservableObject {
@Published var infoX = [
InfoData(nameX: "Example", numberX: 1)
]
func bindingForItem(item: InfoData) -> Binding<InfoData> {
.init {
self.infoX.first { [=12=].id == item.id }!
} set: { newValue in
self.infoX = self.infoX.map { [=12=].id == item.id ? newValue : [=12=] }
}
}
}
struct ContentView: View {
@StateObject var contentX = ContentX()
var body: some View {
List(contentX.infoX) { item in
HStack {
Text("\(item.nameX)")
Spacer()
Button("+") {
contentX.bindingForItem(item: item).wrappedValue.numberX += 1
}
Text("\(item.numberX)")
}
}
}
}