3

在 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
}

像 people[keyPath: \[People].all.name] = "全部更新而不手动迭代"

4

2 回答 2

3

变异为数组的成员需要一个左值。Swift 的左值机制是下标,所以我们可以使用它:

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在你有一个现有的闭包/函数要传递的情况下,其中有 type (Index) -> Void

// meh
people.indices.forEach {
    people[$0][keyPath: \Person.name] = "updated"
}
于 2018-02-13T01:23:45.073 回答
-1

编辑回应您现在编辑的问题,询问 Swift 的等价物在哪里[people makeObjectsPerformSelector: @selector(setName:) withObject: @"updated"],简单的答案是map,您出于某种原因拒绝在您的问题中,等价的。当然,要做Objective-C所做的事情,我们必须使用Objective-C风格的对象类型,即一个类:

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"
}

map不过,据我所知,这实际上并不比使用更有效;结构在适当的位置是不可变的,所以我们仍然用全新的 Person 对象填充数组,就像我们在使用map.

于 2018-02-13T01:25:16.557 回答