在我的last question中,我问如何在Swift中为set属性的下标编写setter。我认为我的问题不足以让人理解。对于小型任务,给出的答案要么不正确,要么复杂。经过长时间的思考,我仍然认为一个更聪明的人可以提供更有启发性的答案。
为了消除混淆,我的问题是如果在Swift中有一个数组下标的简写setter声明。因为在swift中有一个数组的简写setter声明,而不是它的下标。
简写getter / setter声明是
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)
}
上面的解决方案很容易理解,但是,它需要一个函数,它在一个类中需要两行代码。 不太“Swift”。
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
答案 0 :(得分:4)
你不理解的是,普通的setter 是你正在寻找的速记。如果一个对象有一个数组属性而某人设置了该数组,那么就会调用该setter。
例如:
class Thing {
var arr : [Int] = [1, 2, 3] {
didSet {
println("I saw that")
}
}
}
var t = Thing()
t.arr[1] = 100 // "I saw that"
所以你要做的就是使用didSet
将新值与旧值进行比较,然后根据自己的喜好做出反应。
答案 1 :(得分:1)
我确实想到了另一种方式,但我不喜欢它。使用扩展名将另一个下标添加到setter to 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"