Невозможно назначить "X" в "Y" в Swift
У меня есть словарь с Structs
. Я пытаюсь присвоить значения struct
, когда я прохожу через dictionary
. Свифт говорит мне cannot assign to 'isRunning' in 'blockStatus'
. Я не смог найти что-либо в документах по этой конкретной неизменности dictionaries
или Structs
.
Прямо с детской площадки:
import Cocoa
struct BlockStatus{
var isRunning = false
var timeGapForNextRun = UInt32(0)
var currentInterval = UInt32(0)
}
var statuses = ["block1":BlockStatus(),"block2":BlockStatus()]
for (block, blockStatus) in statuses{
blockStatus.isRunning = true
}
cannot assign to 'isRunning' in 'blockStatus'
blockStatus.isRunning = true
Это работает, если я изменяю struct
на class
.
Я предполагаю, что это имеет какое-то отношение к тому факту, что структуры копируются и классы всегда ссылаются?
РЕДАКТИРОВАТЬ: Итак, даже если он копирует его. Почему я не могу его изменить? Это даст мне неправильный результат, но вы можете изменить членов констант, а не сами константы. Например, вы можете сделать это:
class A {
var b = 5
}
let a = A()
a.b = 6
Ответы
Ответ 1
Ваше предположение верно.
Получив доступ к blockStatus
, вы создаете его копию, в этом случае это постоянная копия (итераторы всегда постоянны).
Это похоже на следующее:
var numbers = [1, 2, 3]
for i in numbers {
i = 10 //cannot assign here
}
Литература:
Контроль потока
В приведенном выше примере индекс является константой константой, значение которой автоматически устанавливается в начале каждой итерации цикла.
Классы и структуры
Тип значения - это тип, который копируется, когда ему присваивается переменная или константа или когда она передается функции. [...] Все структуры и перечисления являются типами значений в Swift
Methods
Структуры и перечисления представляют собой типы значений. По умолчанию свойства типа значения не могут быть изменены из его методов экземпляра.
Однако, если вам нужно изменить свойства вашей структуры или перечисления в определенном методе, вы можете выбрать способ изменения для этого метода. Затем этот метод может мутировать (то есть изменять) его свойства внутри метода, и любые изменения, которые он делает, записываются обратно в исходную структуру, когда метод заканчивается. Этот метод также может назначить полностью новый экземпляр его неявному свойству self, и этот новый экземпляр заменит существующий, когда метод завершится.
Вы можете выбрать это поведение, поставив ключевое слово mutating перед ключевым словом func для этого метода:
Ответ 2
Вы можете пропустить массив с индексом
for index in 0..<statuses.count {
// Use your array - statuses[index]
}
который должен работать, не получив "невозможно назначить"
Ответ 3
Если "Y" в этом случае является протоколом, подставьте свой протокол к class
. У меня был протокол:
protocol PlayerMediatorElementProtocol {
var playerMediator:PlayerMediator { get }
}
и попытался установить playerMediator
из посредника моего игрока:
element.playerMediator = self
Который превратился в ошибку cannot asign 'playerMediator' in 'element'
Изменение моего протокола для наследования класса исправлено:
protocol PlayerMediatorElementProtocol : class {
var playerMediator:PlayerMediator { get }
}
Почему он должен наследовать от класса?
Причина, по которой он должен наследовать от class
, заключается в том, что компилятор не знает, какой тип вашего унаследован. Структуры также могут наследовать этот протокол, и вы не можете назначить свойство постоянной структуры.