Swift: как изменить значение свойства без вызова его функции didSet
Как вы можете установить значение свойства в Swift, не вызывая его функцию didSet()
вне контекста инициализации? Код ниже был неудачным экспериментом для достижения этого в функции классов noside()
class Test
{
var toggle : Bool = 0
var hoodwink : Int = 0 {
didSet(hoodwink)
{
toggle = !toggle
}
}
// failed attempt to set without a side effect
func noside(newValue : Int)
{
hoodwink = newValue
println("hoodwink: \(hoodwink) state: \(toggle)")
}
func withside(newValue : Int)
{
self.hoodwink = newValue
println("hoodwink: \(hoodwink) state: \(toggle)")
}
}
В Objective-C довольно сложно выполнять функции с автосинтезом:
С побочным эффектом (если присутствует в сеттере):
self.hoodwink = newValue;
Без побочного эффекта:
_hoodwink = newValue;
Ответы
Ответ 1
Что вы делаете в Objective-C для "предотвращения побочных эффектов" - это доступ к хранилищу резервных копий свойства - его переменной экземпляра, которая по умолчанию имеет префикс подчеркивания (вы можете изменить это с помощью директивы @synthesize
).
Однако, похоже, что разработчики языка Swift проявили особую осторожность, чтобы сделать невозможным доступ к переменным поддержки для свойств: согласно книге,
Если у вас есть опыт работы с Objective-C, вы можете знать, что он предоставляет два способа хранения значений и ссылок как часть экземпляра класса. В дополнение к свойствам вы можете использовать переменные экземпляра в качестве хранилища резервных копий для значений, хранящихся в свойстве.
Swift объединяет эти понятия в одно объявление свойства. Свойство Swift не имеет соответствующей переменной экземпляра, а хранилище резервных копий для свойства напрямую не обращается. (акцент мой)
Конечно, это относится только к использованию средства "обычного языка", а не к использованию рефлексии: это может обеспечить ограничение этого ограничения за счет удобочитаемости.
Ответ 2
Возможный взломать это - создать сеттер, который обходит ваш didSet
var dontTriggerObservers:Bool = false
var selectedIndexPath:NSIndexPath? {
didSet {
if(dontTriggerObservers == false){
//blah blah things to do
}
}
}
var primitiveSetSelectedIndexPath:NSIndexPath? {
didSet(indexPath) {
dontTriggerObservers = true
selectedIndexPath = indexPath
dontTriggerObservers = false
}
}
Уродливый, но работоспособный
Ответ 3
Если вы точно знаете, когда хотите применить побочные эффекты, просто сделайте это явно:
1 Решение:
func noside(newValue : Int) {
hoodwink = newValue
}
func withside(newValue : Int) {
self.hoodwink = newValue
toggle = !toggle
}
2 Решение:
var toggle : Bool = false
var hoodwink : Int = 0
var hoodwinkToggle: Int {
get { return hoodwink }
set(newValue) {
hoodwink = newValue
toggle = !toggle
}
}
- func setHoodwinkWithToggle (hoodwink: Int) {...}
- ....
Я думаю, что эти решения будут более понятными и понятными, а затем использовать одну переменную, которая при некоторых вызовах должна иметь побочные эффекты и не должна быть в других.