如何在Swift 4.0中使用WritableKeyPath更新数组

时间:2018-02-13 01:09:12

标签: arrays swift struct updating keypaths

在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] ="无需手动迭代即可全部更新"

2 个答案:

答案 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时一样。