Swift 改变变量的结构不起作用?
Swift struct mutating a variable not working?
即使在方法中使用 mutating func
关键字,我也无法修改我的模型 class 变量?
所以基本上我用一种非常简单的方式解决了我的问题我有一个 class Car
有 3 个变量 id
、start
和 modelNo
之后初始化一个空的汽车模型数组,然后我想显示 10 辆汽车,创建一个循环范围 1...10
,初始化汽车模型 class 并将其附加到原始汽车数组。
检查前 5 辆汽车的 ID 为 0,后 5 辆汽车的 ID 为 1
我想要一个过滤器,其中相同 ID 的最后一辆车将启动,所以我创建了一个方法来过滤和修改启动变量但无法修改它。你能帮我做错什么吗?
请查看我的完整代码并将其复制粘贴到 playground。
struct Car {
var id = 0
var start = false
var modelNo: String
init(start: Bool, id: Int, model: String) {
self.start = start
self.id = id
self.modelNo = model
}
mutating func startCar(status: Bool) {
start = status
}
}
var arrCars:[Car] = [Car]()
for i in 1...10 {
let md = Car(start: false, id: i <= 5 ? 0 : 1, model: "Model\(i)")
arrCars.append(md)
}
private func filtered() {
for item in arrCars {
let filteredItems = arrCars.filter { [=11=].id == item.id }
if filteredItems.count > 0 {
if var lastItem = filteredItems.last {
print("Will start \(lastItem.modelNo)")
lastItem.startCar(status: true)
}
}
}
let cars = arrCars.filter { (car) -> Bool in
car.start == true
}
print(cars.count)
}
filtered()
我们将不胜感激。
在结构上创建 mutating
函数不会改变结构的值语义。一旦结构实例发生变异,就会创建一个副本。
你说:
if var lastItem = filteredItems.last {
print("Will start \(lastItem.modelNo)")
lastItem.startCar(status: true)
}
因此,lastItem
包含您要启动的汽车实例。在幕后,这是 filteredItems
中的汽车实例,与 arrCars
中的实例相同。但是,一旦你改变 lastItem
中的 Car
,就会创建一个副本,因此 lastItem
不再具有与 [=15= 中的实例相同的实例]。 filteredItems
和 arrCars
仍然包含原始的、未更改的 Car
实例。
您可以将 Car
更改为 class
而不是 struct
,以便它具有引用语义以获得您想要的行为。
另一种选择是就地修改实例;类似于 arrCars[0].startCar(status: true)
。为此,您需要获取一个数组,其中包含您要启动的汽车的 indicies 而不是汽车本身:
private func filtered() {
for item in arrCars {
let matchingIndices = arrCars.enumerated().compactMap { (index,car) in
return car.id == item.id ? index:nil
}
if matchingIndices.count > 0 {
if let lastIndex = matchingIndices.last {
print("Will start \(arrCars[lastIndex].modelNo)")
arrCars[lastIndex].startCar(status: true)
}
}
}
let cars = arrCars.filter { (car) -> Bool in
car.start == true
}
print(cars.count)
}
但是,如果模型对象需要可变性或有状态,则结构可能不适合。
首先尝试 运行 这段代码,如果我们坚持 Structure
s,检查它是否解决了问题。然后我将尝试解释为什么这有帮助:
struct Car {
var id = 0
var start = false
var modelNo: String
init(start: Bool, id: Int, model: String) {
self.start = start
self.id = id
self.modelNo = model
}
mutating func startCar(status: Bool) {
start = status
}
}
var arrCars: Array<Car> = [Car]()
for i in 1...10 {
let md = Car(start: false, id: i <= 5 ? 0 : 1, model: "Model\(i)")
arrCars.append(md)
}
private func filtered() {
for item in arrCars {
let filteredItems = arrCars.filter { [=10=].id == item.id }
if filteredItems.count > 0 {
// solves the problem
arrCars[filteredItems.count-1].startCar(status: true)
print("Will start \(arrCars[filteredItems.count-1].modelNo)")
}
}
let cars = arrCars.filter { (car) -> Bool in
car.start == true
}
print(cars.count)
}
filtered()
到目前为止你得到的答案并没有错,但它们似乎有点令人困惑。让我们更简单地看一下。问题是这一行:
if var lastItem = filteredItems.last
这会产生一辆汽车 lastItem
。但它与filteredItems
.
中的不一样
那是因为结构是值类型。赋值 复制 结构。因此,您对 lastItem
所做的操作不会影响 filteredItems
.
中的内容
因此,您不会在改变结构时遇到任何问题。你正在变异 lastItem
就好了!问题是 lastItem
Car 与 filteredItems
.
中的任何 Car 不是同一个对象
即使在方法中使用 mutating func
关键字,我也无法修改我的模型 class 变量?
所以基本上我用一种非常简单的方式解决了我的问题我有一个 class Car
有 3 个变量 id
、start
和 modelNo
之后初始化一个空的汽车模型数组,然后我想显示 10 辆汽车,创建一个循环范围 1...10
,初始化汽车模型 class 并将其附加到原始汽车数组。
检查前 5 辆汽车的 ID 为 0,后 5 辆汽车的 ID 为 1
我想要一个过滤器,其中相同 ID 的最后一辆车将启动,所以我创建了一个方法来过滤和修改启动变量但无法修改它。你能帮我做错什么吗?
请查看我的完整代码并将其复制粘贴到 playground。
struct Car {
var id = 0
var start = false
var modelNo: String
init(start: Bool, id: Int, model: String) {
self.start = start
self.id = id
self.modelNo = model
}
mutating func startCar(status: Bool) {
start = status
}
}
var arrCars:[Car] = [Car]()
for i in 1...10 {
let md = Car(start: false, id: i <= 5 ? 0 : 1, model: "Model\(i)")
arrCars.append(md)
}
private func filtered() {
for item in arrCars {
let filteredItems = arrCars.filter { [=11=].id == item.id }
if filteredItems.count > 0 {
if var lastItem = filteredItems.last {
print("Will start \(lastItem.modelNo)")
lastItem.startCar(status: true)
}
}
}
let cars = arrCars.filter { (car) -> Bool in
car.start == true
}
print(cars.count)
}
filtered()
我们将不胜感激。
在结构上创建 mutating
函数不会改变结构的值语义。一旦结构实例发生变异,就会创建一个副本。
你说:
if var lastItem = filteredItems.last {
print("Will start \(lastItem.modelNo)")
lastItem.startCar(status: true)
}
因此,lastItem
包含您要启动的汽车实例。在幕后,这是 filteredItems
中的汽车实例,与 arrCars
中的实例相同。但是,一旦你改变 lastItem
中的 Car
,就会创建一个副本,因此 lastItem
不再具有与 [=15= 中的实例相同的实例]。 filteredItems
和 arrCars
仍然包含原始的、未更改的 Car
实例。
您可以将 Car
更改为 class
而不是 struct
,以便它具有引用语义以获得您想要的行为。
另一种选择是就地修改实例;类似于 arrCars[0].startCar(status: true)
。为此,您需要获取一个数组,其中包含您要启动的汽车的 indicies 而不是汽车本身:
private func filtered() {
for item in arrCars {
let matchingIndices = arrCars.enumerated().compactMap { (index,car) in
return car.id == item.id ? index:nil
}
if matchingIndices.count > 0 {
if let lastIndex = matchingIndices.last {
print("Will start \(arrCars[lastIndex].modelNo)")
arrCars[lastIndex].startCar(status: true)
}
}
}
let cars = arrCars.filter { (car) -> Bool in
car.start == true
}
print(cars.count)
}
但是,如果模型对象需要可变性或有状态,则结构可能不适合。
首先尝试 运行 这段代码,如果我们坚持 Structure
s,检查它是否解决了问题。然后我将尝试解释为什么这有帮助:
struct Car {
var id = 0
var start = false
var modelNo: String
init(start: Bool, id: Int, model: String) {
self.start = start
self.id = id
self.modelNo = model
}
mutating func startCar(status: Bool) {
start = status
}
}
var arrCars: Array<Car> = [Car]()
for i in 1...10 {
let md = Car(start: false, id: i <= 5 ? 0 : 1, model: "Model\(i)")
arrCars.append(md)
}
private func filtered() {
for item in arrCars {
let filteredItems = arrCars.filter { [=10=].id == item.id }
if filteredItems.count > 0 {
// solves the problem
arrCars[filteredItems.count-1].startCar(status: true)
print("Will start \(arrCars[filteredItems.count-1].modelNo)")
}
}
let cars = arrCars.filter { (car) -> Bool in
car.start == true
}
print(cars.count)
}
filtered()
到目前为止你得到的答案并没有错,但它们似乎有点令人困惑。让我们更简单地看一下。问题是这一行:
if var lastItem = filteredItems.last
这会产生一辆汽车 lastItem
。但它与filteredItems
.
那是因为结构是值类型。赋值 复制 结构。因此,您对 lastItem
所做的操作不会影响 filteredItems
.
因此,您不会在改变结构时遇到任何问题。你正在变异 lastItem
就好了!问题是 lastItem
Car 与 filteredItems
.