Swift struct, изменяющая переменную, не работает?
Я не могу изменить свою переменную класса модели, даже используя mutating func
ключевое слово в методе?
В общем, я очень легко обернул свою проблему, у меня есть класс Car
который имеет 3 переменных id
, start
, а также modelNo
После этого инициализируйте пустой массив моделей автомобилей, а затем я хочу показать 10 автомобилей, создав диапазон для цикла, который повторяется 1...10
, инициализируя класс модели Car и добавляя его в массив оригинальных автомобилей.
Идет проверка первых 5 автомобилей с идентификатором 0 и последними 5 автомобилями с идентификатором 1
Мне нужен фильтр, в котором будет запускаться последняя машина этого же идентификатора, поэтому я создал метод, отфильтрованный и модифицирующий переменную запуска, но не в состоянии изменить его. Можете ли вы помочь мне, что я делаю не так?
Пожалуйста, посмотрите мой полный код и скопируйте его на игровую площадку.
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 { $0.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()
Любая помощь будет оценена.
3 ответа
Создание mutating
Функция на структуре не меняет семантику значений структур. Как только экземпляр структуры мутирует, создается копия.
Ты говоришь:
if var lastItem = filteredItems.last {
print("Will start \(lastItem.modelNo)")
lastItem.startCar(status: true)
}
Так, lastItem
содержит экземпляр автомобиля, который вы собираетесь запустить. Под крышками это тот же экземпляр автомобиля, который находится в filteredItems
, который является тем же экземпляром, который находится в arrCars
, Но, как только вы мутируете Car
в lastItem
копия сделана, так lastItem
больше не имеет тот же экземпляр, что и вarrCars
, filteredItems
а также arrCars
до сих пор содержат оригинал, без изменений Car
пример.
Ты можешь измениться Car
быть class
а не struct
так что у него есть ссылочная семантика для получения желаемого поведения.
Другой вариант - изменить экземпляр на месте; что-то вроде arrCars[0].startCar(status: true)
, Для этого вам нужно получить массив с указанием автомобилей, которые вы хотите запустить, а не сами автомобили:
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)
}
Однако, когда объект модели требует изменчивости или состояния, структура, вероятно, не подходит.
Ответы, которые вы получили до сих пор, не являются неправильными, но они кажутся немного запутанными. Давайте посмотрим на это немного проще. Проблема в этой строке:
if var lastItem = filteredItems.last
Это дает автомобиль как lastItem
, Но это не та же машина, что и та, что в filteredItems
,
Это потому, что структура является классом значений. Назначение копирует структуру. Таким образом, что вы делаете для lastItem
не влияет на то, что сидит внутри filteredItems
,
Таким образом, у вас нет проблем с изменением структуры. Вы мутируете lastItem
просто хорошо! Проблема в том, что lastItem
Автомобиль не тот же объект, что и любой автомобиль внутри filteredItems
,
Во-первых, попробуйте запустить этот код и проверить, если он решает проблему, если мы придерживаемся 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 { $0.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()