简体   繁体   English

更改数组属性时,Swift映射不起作用

[英]Swift map doesn't work when changing array property

I have the following struct, with some properties: 我有以下结构,有一些属性:

struct Partner {
    let id: Int
    let nome: String
    let icone: String
    var isSelected : Bool
}

So I initialize a simple array and put some data in there: 所以我初始化一个简单的数组并在其中放入一些数据:

var parceiros : [Partner] = [
    Partner(id: 1, nome: "Personal Profile", icone: "btPersonal",isSelected : true),
    Partner(id: 2, nome: "Professional Profile", icone: "btProfessional", isSelected: false)
]

But when I want to change the "isSelected" property with the high-order function Map, in the swift 4, the array don't update at all. 但是当我想用高阶函数Map更改“isSelected”属性时,在swift 4中,数组根本不会更新。 Its weird because the var "_parceiro" have the right value in the return loop. 它很奇怪,因为var“_parceiro”在返回循环中具有正确的值。 But after the function the array returns to the original value. 但是在函数之后,数组返回到原始值。

private func select(partner: Partner){
    let _ = parceiros.map { (parceiro) -> Partner in
        var _parceiro = parceiro
        _parceiro.isSelected = parceiro.id == partner.id ? true : false
        return _parceiro
    }
}

You are confusing reference and value types. 您会混淆参考和值类型。 While you working with Swift arrays of structs (struct is value-type), they creating a copy of anything you are putting in it. 当您使用Swift数组结构(struct是value-type)时,它们会创建您放入其中的任何内容的副本 When you retrieving anything from the struct, it will make another copy of it. 当您从结构中检索任何内容时,它将生成另一个副本 Basically map creation a new array of new structs taken from old array. 基本上映射创建从旧数组中获取的新结构的新数组。 You had to assign that array back: 你必须分配该数组:

private func select(partner: Partner){
    parceiros = parceiros.map { (parceiro) -> Partner in
        var _parceiro = parceiro
        _parceiro.isSelected = parceiro.id == partner.id ? true : false
        return _parceiro
    }
}

Or you can use reference type: class. 或者您可以使用引用类型:class。 It means that instead of keeping copies of your structs, array will keep references to actual instance of the objects. 这意味着数组将保留对对象的实际实例的引用,而不是保留结构的副本。

class Partner {
    let id: Int
    let nome: String
    let icone: String
    var isSelected : Bool
}

And the change a particular object inside it. 并改变其中的特定对象。 You don't need to map then though. 但是,您不需要映射。 If you want to apply something for each member of array use forEach , if you want to apply something to part of array - use filter first: 如果你想为每个数组成员使用forEach ,如果你想将某些东西应用到数组的一部分 - 首先使用filter

private func select(partner: Partner){
        parceiros.forEach {  $0.isSelected = (parceiro.id == partner.id) }
}

map is not a mutating function. map不是一个变异函数。 It can be used to iterate over a collection and apply the same transformation function to all elements of the collection, storing the transformed values in a new collection and returning that new collection. 它可用于迭代集合并将相同的转换函数应用于集合的所有元素,将转换后的值存储在新集合中并返回该新集合。

You either need to use a simple loop and manually modify the selected value in the original array or simply use the return value of map . 您需要使用一个简单的循环并手动修改原始数组中的选定值,或者只使用map的返回值。

private func select(partner: Partner) -> [Partner] {
    return parceiros.map { (parceiro) -> Partner in
        var _parceiro = parceiro
        _parceiro.isSelected = parceiro.id == partner.id
        return _parceiro
    }
}

parceiros = select(parceiros[0])

If you want to go for the map approach, you can also simplify the closure to a single line like below: 如果你想使用map方法,你也可以将闭包简化为单行,如下所示:

private func select(partner: Partner, from partners: [Partner]) -> [Partner] {
    return partners.map { return Partner(id: $0.id, nome: $0.nome, icone: $0.icone, isSelected: $0.id == partner.id)}
}

let selectedPartners = select(partner: parceiros[1], from: parceiros)

The approach using a regular loop: 使用常规循环的方法:

private func select(partner: Partner){
    for i in parceiros.indices {
        parceiros[i].isSelected = parceiros[i].id == partner.id
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM