Подтвердить что ты не робот

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;
4b9b3361

Ответ 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
    }
}
  1. func setHoodwinkWithToggle (hoodwink: Int) {...}
  2. ....

Я думаю, что эти решения будут более понятными и понятными, а затем использовать одну переменную, которая при некоторых вызовах должна иметь побочные эффекты и не должна быть в других.