Сокращенное объявление сеттера для индекса массива в 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
сравнить новое значение со старым значением и отреагировать так, как вам нравится.