更改数组属性时,Swift地图不起作用

时间:2018-10-03 15:17:37

标签: ios arrays swift

我具有以下具有某些属性的结构:

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

所以我初始化了一个简单的数组,并在其中放置了一些数据:

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

但是,当我想使用高阶函数Map更改“ isSelected”属性时,在swift 4中,数组根本不会更新。这很奇怪,因为var“ _parceiro”在返回循环中具有正确的值。但是在该函数之后,数组将返回到原始值。

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

2 个答案:

答案 0 :(得分:1)

您正在混淆引用和值类型。在使用Swift的结构数组(struct是值类型)时,它们会为您要放入的所有内容创建一个副本。当您从结构中检索任何内容时,它将对其进行另一个副本。基本上,地图创建是从旧数组中获取新结构的新数组。您必须将该数组分配回去:

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

或者您可以使用引用类型:类。这意味着,数组将保留对对象实际实例的引用,而不是保留结构的副本。

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

然后更改其中的特定对象。不过,您不需要映射。如果要对数组的每个成员应用某些内容,请使用forEach,如果要对数组的一部分应用某些内容-请首先使用filter

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

答案 1 :(得分:0)

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])

如果您想采用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)

使用常规循环的方法:

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