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"