如何使用 Xcode 6.3 Beta2 覆盖 Swift 中超类的 setter?

How can I override a setter from a SuperClass in Swift with Xcode 6.3 Beta2?

我的 SuerClass 是 UICollectionViewCell,它有一个 属性:

var selected: Bool

我的 class 是

MyClass : UICollectionViewCell {

  func setSelected(selected: Bool) { 
    super.selected = selected
    // do something
 }

}

前者在 Xcode 6.2 中运行良好,但在 Xcode 6.3Beta2 中出现错误:

Method 'setSelected' with Objective-C selector 'setSelected:' conflicts with setter for 'selected' from superclass 'UICollectionViewCell' with the same Objective-C selector

如何解决此问题以与 Xcode 6.3 beta2 一起使用?

编辑:我也尝试过:

  override func setSelected(selected: Bool) { 
    super.selected = selected
    // do something
 }

这会导致错误:

Method does not override any method from its superclass

如果我们希望它在设置 selected 属性 之后做一些额外的功能,我们可以简单地重写以添加一个 属性 观察者:

override var selected: Bool {
    didSet {
        if self.selected {
            // do something
        }
    }
}

Swift 5 的更新答案:

override var isSelected: Bool {
    didSet {
        if self.isSelected {
            // do something
        }
    }
}

如果我们关心 selected 的先前值是什么,我们可以通过 oldValue:

访问它
didSet {
    if self.selected == oldValue {
        return
    }
    // do something
}

Swift 5 的更新答案:

didSet {
    if self.isSelected == oldValue {
        return
    }
    // do something
}

别忘了,如果我们需要在更改值之前做一些事情,我们也可以使用 willSet


我很好奇当我们有一个很大的 classes 层次结构时会发生什么,每个人都在 willSetdidSet 属性 观察者中添加自己的东西,所以我创建了以下测试:

class ClassA {
    var _foo: Int = 0
    var foo: Int {
        set(newValue) {
            println("Class A setting foo")
            self._foo = newValue
        }
        get {
            return self._foo
        }
    }
}

class ClassB: ClassA {
    override var foo: Int {
        willSet {
            println("Class B will set foo")
        }
        didSet {
            println("Class B did set foo")
        }
    }
}

class ClassC: ClassB {
    override var foo: Int {
        willSet {
            println("Class C will set foo")
        }
        didSet {
            println("Class C did set foo")
        }
    }
}

现在,如果我们创建一个 ClassC 的 object 并设置它的 foo 属性:

var c: ClassC = ClassC()  
c.foo = 42

我们得到以下输出:

Class C will set foo
Class B will set foo
Class A setting foo
Class B did set foo
Class C did set foo

因此,请务必注意以下几点...

  • A child class 的 willSet 在 其 parent 的 willSet 之前被称为
  • A child class 的 didSet 被称为 其 parent 的 didSet 之后。
  • 为了添加 属性 观察者而创建覆盖 不会 替换 parent [=71= 中的任何 属性 观察者]es.

前两点有点道理。实际上,这让 属性 观察者更具吸引力。实际上,Swift 迫使我们的手以适当的方式在层次结构中上下移动,并将其很好地分成两个单独的方法。 Swift 也阻止我们(我相信)覆盖 parent class 的 属性,但仍然让我们观察到 属性 的变化——这个比Objective-C的方法好多了。

但第三点可能是最重要的。小心——您很容易陷入 didSetwillSet 代码的巨大层次结构中,这会减慢本来应该非常快速的过程:设置 属性 的值。