jul*_*ong 6 arrays swift swift-structs
我正在尝试修改数组中的结构元素。我发现您可以通过按索引访问(迭代)结构来做到这一点,但如果您使用“for in”循环或 forEach{},则不能。
struct Person
{
var age = 0
var name = "James"
}
var personArray = [Person]()
personArray += [Person(), Person(), Person()]
personArray.forEach({$0.age = 10}) // error: "Cannot assign to property: '$0' is immutable"
for person in personArray {
person.age = 10 // error: "Cannot assign to property: 'person' is a 'let' constant"
}
for index in personArray.indices {
personArray[index].age = 10 // Ok
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下吗?
Lou*_*Lac 10
正如其他答案中所述,您不能在for-in循环或.forEach方法中进行变异。
您可以使用简短而简洁的最后一个公式:
for index in personArray.indices {
personArray[index].age = 10
}
Run Code Online (Sandbox Code Playgroud)
或者personArray完全改变原始:
personArray = personArray.map { person in
var person = person // parameter masking to allow local mutation
person.age = 10
return person
}
Run Code Online (Sandbox Code Playgroud)
请注意,第二个选项似乎效率较低,因为它Person每次都会创建一个新实例,但 Swift 似乎针对这些情况进行了很好的优化。时间探查器报告第二个选项的操作速度快了近 2 倍,数组为 1 000 000Person秒。
如果您真的想要.forEach方法的变异对应物,这是一个奖励,请使用扩展名MutableCollection:
extension MutableCollection {
mutating func mutateEach(_ body: (inout Element) throws -> Void) rethrows {
for index in self.indices {
try body(&self[index])
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个相当于您的第一个公式的数组突变的包装器,您可以按预期使用它:
personArray.mutateEach { $0.age = 10 }
Run Code Online (Sandbox Code Playgroud)
在 Swift 中,结构体是一种值类型。在 for 或 foreach 循环中,person 项是一个值,如果它是可变的,您将只更改原始副本,而不是您想要的原始副本。
如果您真的想要对循环内结构的可更新引用,请添加 var 关键字,但请记住,您更新的是副本而不是原始副本。
for var person in personArray {
person.age = 10 // updates a copy, not the original
}
Run Code Online (Sandbox Code Playgroud)
相比之下, class 是一种引用类型,在循环中,每一项都是对原始项的引用。现在更新此参考值会更新原始值。
将 Person 的定义更改为 class 而不是 struct ,它将按预期工作。有关完整说明,请参阅https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html