【问题标题】:Swift map doesn't work when changing array property更改数组属性时,Swift map 不起作用
【发布时间】:2026-01-23 13:20:08
【问题描述】:

我有以下结构,具有一些属性:

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

【问题讨论】:

  • 小提示:parceiros.map { (parceiro) -> Partner inResult of call to 'map' is unused@Result of call to 'map' is unused@@Result of call to 'map' is unused@@Result of call to 'map' is unused@Result of call to 'map' is unused@Result of call to 'map' is unused@Result of call to 'map' is unused@@Result of call to 'map' is unused@@Result of call to 'map' is unused@@Result of call to 'map' is unusedResult of call to 'map' is unusedResult of call to 'map' is unused
  • 这不是要让它沉默的暗示,这是因为响应在其中。 map() 返回转换后的结果,不会修改调用它的当前对象,不是变异方法。

标签: ios arrays swift


【解决方案1】:

您混淆了引用类型和值类型。当您使用 Swift 结构数组(结构是值类型)时,它们会创建您放入其中的任何内容的 副本。当您从结构中检索任何内容时,它会制作另一个 副本。基本上映射创建从旧数组中获取的新结构的新数组。您必须重新分配该数组:

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。这意味着数组将保留对对象实际实例的引用,而不是保留结构的副本。

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

【讨论】:

    【解决方案2】:

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

    【讨论】: