Swift中数组下标的速记setter声明

时间:2015-01-18 00:47:02

标签: arrays swift dynamic-properties

在我的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

因此,是否存在类似与第二种解决方案的解决方案,但有效

2 个答案:

答案 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"