Сокращенное объявление сеттера для индекса массива в Swift

В своем последнем вопросе я спросил, как написать setter для индекса вычисляемого свойства в Swift. Я думаю, что мой вопрос не был достаточно существенным, чтобы быть понятым. Данный ответ был либо неправильным, либо сложным для небольшой задачи. После долгих размышлений я все еще думаю, что, может быть, более яркий человек может предложить более вдохновляющий ответ.

Чтобы избежать путаницы, мой вопрос заключается в том, существует ли стенографическое объявление для нижнего индекса массива в Swift. Потому что есть краткая декларация сеттера для массива в swift, но не его нижний индекс.

Сокращенное объявление getter/setter is

var center: Point {
    get {
        let centerX = origin.x + (size.width / 2)
        let centerY = origin.y + (size.height / 2)
        return Point(x: centerX, y: centerY)
    }
    set {
        origin.x = newValue.x - (size.width / 2)
        origin.y = newValue.y - (size.height / 2)
    }
}

В основном, в сценарии, где заданное действие для action[i] вызовет actionButton[i] быть обновленным. Есть два основных способа сделать это быстро.

Первое решение

func setActionAtIndex(index:Int, forValue newValue:SomeClass){
    action[index] = newValue
    self.updateActionButtonAtIndex(index)
}

Приведенное выше решение легко понять, однако для него требуется функция, которая занимает две строки кода в одном классе. Не совсем "Свифт".

Второе решение

var action: [SomeClass] {
    subscript(index:Int){
        set(index:Int,newValue:SomeClass){
           action[index] = newValue
           //extra action to be performed 
           updateActionButtonAtIndex(index)

        }
        get{
           return action[index]
        }
    }
}

Само собой разумеется, это абсолютно неправильно, и это решение не существует.

Почему это неправильно?

Expected 'get', 'set', 'willSet', or 'didSet' keyword to start an accessor definition

Следовательно, есть ли решение, которое похоже на второе решение, но работает?

2 ответа

Решение

Я думал о другом, но мне это не очень нравится. Используйте расширение, чтобы добавить еще один нижний индекс для setter для Array - setter, который позволяет вам предоставлять обратный вызов. Проблема с этим подходом заключается в том, что вы не забыли предоставить обратный вызов! Это накладывает ответственность на тех, кто входит в индекс, что, вероятно, не то, что вы имели в виду. Тем не менее, он имеет преимущество, после настройки, краткости - и это требует O(0) время:

extension Array {
    subscript(ix:Int, f:(T,T,Int)->Void) -> T {
        set {
            let old = self[ix]
            self[ix] = newValue
            f(old,newValue,ix)
        }
        get {
            return self[ix]
        }
    }
}

class Thing {
    var arr : [Int] = [1, 2, 3]
    func f (oldv:Int, newv:Int, ix:Int) {
        println("changed \(oldv) to \(newv) at \(ix)")
    }
}

var t = Thing()
t.arr[1,t.f] = 100 // "changed 2 to 100 at 1"

Что вы не понимаете, так это то, что обычный сеттер - это сокращение, которое вы ищете. Если у объекта есть свойство массива и кто-то устанавливает этот массив, вызывается установщик.

Например:

class Thing {
    var arr : [Int] = [1, 2, 3] {
        didSet {
            println("I saw that")
        }
    }
}

var t = Thing()
t.arr[1] = 100 // "I saw that"

Так что все, что вам нужно сделать, это использовать didSet сравнить новое значение со старым значением и отреагировать так, как вам нравится.

Другие вопросы по тегам