【问题标题】:Swift iOS -How come I can loop through an array of class objects and make property changes but not structs [duplicate]Swift iOS - 我为什么可以循环遍历一组类对象并进行属性更改但不能更改结构[重复]
【发布时间】:2019-08-06 18:20:29
【问题描述】:

如果我遍历 Class 对象的数组,我可以对其上的属性进行更改

class Country {
    var name: String?
    var region: String?

    init(name: String?, region: String?) {
        self.name = name
        self.region = region
    }
}

let canada = Country(name: "Canada", region: "North America")
let mexico = Country(name: "Mexico", region: "North Ameria")
let france = Country(name: "France", region: "Europe")
let korea = Country(name: "Korea", region: "Asia")

var countryArr = [canada, mexico, france, korea]

// this works fine
let transformed = countryArr.map { $0.name = "Random" }

但如果我用Struct 对象尝试这个,我会得到

无法分配给属性:“$0”是不可变的

struct Country {
    var name: String?
    var region: String?
}

var canada = Country(name: "Canada", region: "North America")
var mexico = Country(name: "Mexico", region: "North Ameria")
var france = Country(name: "France", region: "Europe")
var korea = Country(name: "Korea", region: "Asia")

var countryArr = [canada, mexico, france, korea]

// this gets an error
let transformed = countryArr.map { $0.name = "Random" }

【问题讨论】:

    标签: swift class struct


    【解决方案1】:

    这个问题是由于structs 是值类型,所以改变结构的任何属性也会改变结构实例本身,并且map 中的闭包输入参数是不可变的。因此,当您尝试在 map 的闭包中更改属性 $0 时,您正在尝试更改 $0 本身,以防在值类型集合上调用 map

    另一方面,classes 是引用类型,因此改变 class 实例的属性不会改变实例本身。

    您的问题的解决方案是在map 中创建结构实例的可变副本,改变其name 属性并返回它。有两种解决方案,如果你的类型有少量属性,调用它的成员初始化器更容易,但是如果你有很多属性并且只想改变一些,复制结构然后修改必要的属性是更好的选择。

    let transformed = countryArr.map { Country(name: "Random", region: $0.region) }
    let transformed2 = countryArr.map { country->Country in
        var copy = country
        copy.name = "Random"
        return copy
    }
    

    【讨论】:

    • 您好,感谢您的解释。我不能在 2 分钟内投票,所以请稍等。
    • let transformed = countryArr.indices.map { countryArr[$0].name = "Random" } 也应该可以工作
    • @E.Coms 如果countryArr 是可变的,它确实有效,但即使数组本身是不可变的,其他两种解决方案也有效。如果属性本身是不可变的,第一个解决方案甚至可以工作。
    • @DávidPásztor 所以在结构上使用 .map {$0 } 实际上会尝试更改原始结构的内存地址,还是会尝试在新的内存地址创建新结构?
    • @LanceSamaria 您的示例实际上不会编译,因为正如我在回答中已经说过的,闭包输入参数是不可变的。正如我已经说过的,结构体是值类型,所以改变结构体属性也会改变结构体实例本身
    猜你喜欢
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    相关资源
    最近更新 更多