在Swift 4.0中,我有一个结构数组。有没有办法使用keyPaths更新数组中的所有项目而不使用map或forEach手动迭代?类似于objc [people makeObjectsPerformSelector: @selector(setName:) withObject: @"updated"];
struct Person {
var name: String? = "Empty"
}
var people = [Person(), Person()]
//This only updates one person:
people[keyPath: \[Person].[0].name] = "single update"
//I'm looking to accomplish something like this without a map
let updatedPeople = people.map { (person: Person) -> Person in
var copy = person
copy[keyPath: \Person.name] = "updated"
return copy
}
等等
人[keyPath:\ [People] .all.name] ="无需手动迭代即可全部更新"
答案 0 :(得分:1)
变换为数组成员需要l值。 Swift的l值机制是下标,所以我们可以使用:
for i in people.indices {
people[i][keyPath: \Person.name] = updated
// or more simply, just:
// people[i].name = "updated"
// This even works too, but I can't see any reason why it would be desirable
// over the other 2 approaches:
// people[keyPath: \[Person].[i].name] = "update"
}
你也可以使用forEach
,但我通常只建议在for
以上的情况下你有一个现有的传递闭包/函数,其类型为(Index) -> Void
:
// meh
people.indices.forEach {
people[$0][keyPath: \Person.name] = "updated"
}
答案 1 :(得分:-1)
编辑回复您现在编辑的问题,询问Swift等效于free_result
的位置,简单的答案是[people makeObjectsPerformSelector: @selector(setName:) withObject: @"updated"]
,您出于某种原因在您的问题中拒绝,是那个等价物。当然,要做Objective-C所做的事情,我们必须使用Objective-C样式的对象类型,即一个类:
map
已加星标的行 如何使数组中的对象执行“选择器”。
结构是一种值类型,正如你在问题中正确地说的那样,我们必须插入一个带有class Person {
var name: String? = "Empty"
}
var people = [Person(), Person()]
people = people.map {$0.name = "updated"; return $0} // *
引用的临时变量:
var
[原始答案:]
在你的问题中使用关键路径似乎是一个红色的鲱鱼。您只是想知道如何设置数组中所有结构的属性。
struct Person {
var name: String? = "Empty"
}
var people = [Person(), Person()]
people = people.map {var p = $0; p.name = "updated"; return p}
只是循环数组的一种方式。你不能神奇地做这个没有在数组中循环;如果你没有明确地这样做,你必须隐含地这样做。
这是一种明确的方式:
map
据我所知,这实际上并不比使用struct Person {
var name: String? = "Empty"
}
var people = [Person(), Person()]
let kp = \Person.name
for i in 0..<people.count {
people[i][keyPath:kp] = "updated"
}
更有效率;结构不是可变的,因此我们仍然使用全新的Person对象填充数组,就像使用map
时一样。