Shorthand setter Swift 中数组下标的声明
Shorthand setter declaration for a subscript of an array in Swift
在我的 last question 中,我询问了如何为 Swift 中计算的 属性 的下标编写 setter。我认为我的问题不足以被理解。对于一项小任务,给出的答案要么不正确,要么复杂。思索良久,我还是觉得也许有更聪明的人可以提供更鼓舞人心的答案。
为了平息混乱,我的问题是 如果 Swift 中的数组下标有 shorthand setter 声明。因为 swift 中的数组有 shorthand setter 声明,但没有它的下标。
一个shorthandgetter/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)
}
上面这个方案很好理解,但是需要一个函数,两行代码合二为一class。 不完全是 "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
因此,是否有与第二个解决方案相似但有效的解决方案?
您不明白的是,一个普通的 setter 是 您正在寻找的 shorthand。如果一个对象有一个数组 属性 并且有人设置到该数组,则调用 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
将新值与旧值进行比较,然后根据您的喜好对更改做出响应。
我也有想过别的办法,但不太喜欢。使用扩展将另一个下标添加到 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"
在我的 last question 中,我询问了如何为 Swift 中计算的 属性 的下标编写 setter。我认为我的问题不足以被理解。对于一项小任务,给出的答案要么不正确,要么复杂。思索良久,我还是觉得也许有更聪明的人可以提供更鼓舞人心的答案。
为了平息混乱,我的问题是 如果 Swift 中的数组下标有 shorthand setter 声明。因为 swift 中的数组有 shorthand setter 声明,但没有它的下标。
一个shorthandgetter/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)
}
上面这个方案很好理解,但是需要一个函数,两行代码合二为一class。 不完全是 "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
因此,是否有与第二个解决方案相似但有效的解决方案?
您不明白的是,一个普通的 setter 是 您正在寻找的 shorthand。如果一个对象有一个数组 属性 并且有人设置到该数组,则调用 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
将新值与旧值进行比较,然后根据您的喜好对更改做出响应。
我也有想过别的办法,但不太喜欢。使用扩展将另一个下标添加到 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"