Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 296
confile Avatar asked Mar 14 '15 13:03

confile


People also ask

Can we override properties in Swift?

Classes in Swift can call and access methods, properties, and subscripts belonging to their superclass and can provide their own overriding versions of those methods, properties, and subscripts to refine or modify their behavior.

Can we override class method in Swift?

In Swift Inheritance, the subclass inherits the methods and properties of the superclass. This allows subclasses to directly access the superclass members. Now, if the same method is defined in both the superclass and the subclass, then the method of the subclass class overrides the method of the superclass.

What is override in Xcode?

The override is used when you want to write your own method to replace an existing one in a parent class. It's used commonly when you're working with UIViewControllers , because view controllers already come with lots of methods like viewDidLoad() and viewWillAppear() .

Does Swift support method overriding?

There is no overloading. In Swift you can definitely overload.


1 Answers

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

Updated Answer for Swift 5:

override var isSelected: Bool {
    didSet {
        if self.isSelected {
            // 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
}

Updated Answer for Swift 5:

didSet {
    if self.isSelected == 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.

like image 131
nhgrif Avatar answered Oct 15 '22 10:10

nhgrif