如何使用XCode 6.3 Beta2覆盖Swift中SuperClass的setter? [英] How can I override a setter from a SuperClass in Swift with XCode 6.3 Beta2?

查看:205
本文介绍了如何使用XCode 6.3 Beta2覆盖Swift中SuperClass的setter?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  var选中:Bool 

我的班级是

  MyClass:UICollectionViewCell {

func setSelected(selected:Bool){
super.selected = selected
//做点什么
}

}

前者在XCode 6.2中运行良好但在XCode 6.3中运行良好Beta2它引发了一个错误:

 使用Objective-C选择器'setSelected:'的方法'setSelected'使用相同的Objective-C选择器从超类'UICollectionViewCell'与'selected'的setter冲突

我如何解决这个问题与XCode 6.3 beta2一起使用?



编辑:我也试过了

 覆盖func setSelected(选择:Bool){
super.selected = selected
//做点什么
}

这会导致错误:

 方法不会覆盖其超类中的任何方法


解决方案

如果我们想要它在设置的选择的属性之后执行一些额外的功能,我们可以简单地覆盖以添加属性观察者:

 覆盖var selected:Bool {
didSet {
if self。选择{
//做点什么
}
}
}

如果我们关心选择的先前值是什么,我们可以通过 oldValue 来访问它:

  didSet {
if self.selected == oldValue {
return
}
//做点什么
}

别忘了,我们可以用 willSet 以及我们之前需要做的事情价值被改变。






我很好奇当我们有一个大的类层次结构时,会发生什么自己的东西在 willSet didSet 属性观察者,所以我创建了以下测试:

  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 {
覆盖var foo:Int {
willSet {
println(B类将设置foo)
}
didSet {
println(B类确实设置了foo)
}
}
}

类ClassC:ClassB {
覆盖var foo:Int {
willSet {
println(C类将设置foo)
}
didS et {
println(C类确实设置了foo)
}
}
}

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

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

我们得到以下输出:

  C类将设置foo 
B类将设置foo
A类设置foo
B类设置foo
C类设置foo

因此,重要的是要注意一些事情......




  • 子类的 willSet 在之前被称为其父级的 willSet

  • 子类的 didSet 之后被称为其父级的 didSet

  • 为了添加属性观察者而创建覆盖替换任何正确的父类中的ty观察者。



前两点有点意义。实际上,这使得财产观察者更具吸引力。实际上,斯威夫特以适当的方式强迫我们的手上下层,并很好地将它分成两个独立的方法。 Swift还阻止我们(我相信)覆盖父类的属性,但仍然让我们观察对该属性的更改 - 这比Objective-C的方法要好得多。



<但第三点可能是最重要的。小心 - 你可以很容易地陷入一个巨大的 didSet willSet 代码中,这个代码会减慢是一个非常快速的过程:设置属性的值。


My SuerClass is UICollectionViewCellwhich has a property:

var selected: Bool

My class is

MyClass : UICollectionViewCell {

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

}

The former worked well in XCode 6.2 but in XCode 6.3Beta2 it raises an error:

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

How can I fix this to work with XCode 6.3 beta2?

Edit: I also tried

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

This leads to the error:

Method does not override any method from its superclass

解决方案

If all we want it do some extra functionality after the selected property as been set, we can simply override to add a property observer:

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

If we care about what the previous value of selected was, we can access it via oldValue:

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

And don't forget, we can use willSet as well if we need to do something just before the value is changed.


I was curious what would happen when we've got a large hierarchy of classes each adding their own stuff in willSet and didSet property observers, so I created the following test:

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")
        }
    }
}

Now, if we create an object of ClassC and set its foo property:

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

We get the following output:

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

So, it's important to note a few things from this...

  • A child class's willSet is called before its parent's willSet.
  • A child class's didSet is called after its parent's didSet.
  • Creating an override for the sake of adding property observers does not replace any property observers in the parent classes.

The first two points make a bit of sense. And actually, this makes property observers much more appealing. Effectively, Swift forces our hand into going up and down the heirarchy in the appropriate manner and nicely splits it out into two separate methods. Swift also prevents us (I believe) from overriding a parent class's property, but also still lets us observe changes to that property--this is much better than Objective-C's approach.

But the third point is probably the most important. Be careful--you can easily get bogged down in a massive heirarchy of didSet and willSet code that's slowing down what should be a pretty quick process: setting a property's value.

这篇关于如何使用XCode 6.3 Beta2覆盖Swift中SuperClass的setter?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆