18

All descendants of my specific class are to have a UILabel instance variable. So in my parent class I have var label: UILabel. I want to have it in the sublclass as well, but as an IBOutlet. How do I do this?

I added the IBOutlet of the same name, and added weak to both variable declarations. But I get an error about "Cannot override with a stored property".

How should I be doing this? And is it possible to not have to instantiate the superclass' version as I just want it for subclassing?

7
  • 2
    It isn't clear why you'd even want to do this. Why not just have a different instance variable in the subclass? What's the problem you are really trying to solve?
    – matt
    Commented Aug 1, 2014 at 21:18
  • @matt I have a view controller I'm dequeueing that can be one of two different kinds of similar view controllers. I want to use polymorphism to use their superclass to do the operations. Is there a better way to be doing that?
    – Doug Smith
    Commented Aug 1, 2014 at 21:50
  • @DougSmith edited answer have a look
    – codester
    Commented Aug 1, 2014 at 22:23
  • @DougSmith you can override getter and setter and can connect the outlet to subclass
    – codester
    Commented Aug 1, 2014 at 22:38
  • I still do not see, from your "explanation", why these need to be the same instance variable. All you need is a pointer, common to the superclass, which then points to one variable in class A and to another variable in class B.
    – matt
    Commented Aug 1, 2014 at 22:57

5 Answers 5

20

By doing so you are re-declaring the label property in a subclass. IBOutlet is just a compiler notion for working with the Interface Builder.

In Swift stored properties can not be overridden or redeclared in a subclass. They can only be inherited.

However you can override the getter and setter of a properties in subclasses to provide extra validations or functionalities. Refer to the Swift guide: override getter setter

You need to declare your property in superClass with IBOutlet.

Or you can make a different property in your subclass. As also there is no meaning if you are connecting your property in one of subclasses(super class may have other) and you are not providing this implementation to other subclasses of your superclass.

EDIT: You can also set label outlet to two different viewControllersof your SuperClass from story board if you give Subclasses names in storyboard to different view Controllers.

Just define

 class SuperClass{
     @IBOutlet weak var label: UILabel! = nil

 }

SubClass1 repersent view controller1 in storyboard derived from SuperClass SubClass2 repersent another view controller2 in storyboard derived from SuperClass

Than Go to Assistant Editor and open SuperClass one side and other side view controller1 and connect outlet from SuperClass to label in storyBoard in view controller1.Drag from SuperClass label to storyBoard in view controller1

enter image description here

Now again open SuperClass one side and other side view controller2 and connect outlet from SuperClass to label in storyBoard in view controller2.Drag from SuperClass label to storyBoard in view controller2

If you click on SuperClass outlet than you will see two labels conneted to different viewControllers

3
  • Interesting. Investigating.
    – Doug Smith
    Commented Aug 1, 2014 at 22:40
  • 2
    I simply dont understand the english... Can someone that understands what's going on here please revise this answer. Thanks Commented Feb 17, 2016 at 15:29
  • Seems like this solution does not work if the parent class is generic. Can you confirm, please? Commented Dec 28, 2020 at 11:50
13

Just add the IBOutlet modifier in the superclass.

4
  • How do I then link up the views to the IBOutlet variables?
    – Doug Smith
    Commented Aug 1, 2014 at 21:59
  • The same way as you would without subclassing it. Just set your ViewController to use your subclass and Control+drag the components.
    – B.R.W.
    Commented Aug 1, 2014 at 22:12
  • If I include it in the subclass so I can Control+drag the components I get the same error.
    – Doug Smith
    Commented Aug 1, 2014 at 22:39
  • This only works if you have access to the superclass…
    – shim
    Commented Jul 20, 2017 at 16:00
5

Agreed that the short answer is simply:

"Just add the @IBOutlet modifier in the superclass."

One note though: if you will be exposing the ViewController in which the @IBOutlet is defined via a framework (with Carthage), you will need to add the public attribute to the variable definition. EDIT: instead, use open access keyword`.

Let's say you have a view controller CustomViewController subclassing UITableViewController, which you will build in the Carthage-delivered framework. Everything which should be accessible to the consumer application should be tagged public:

public class CustomViewController: UIViewController {

    override public func viewDidLoad() {
        super.viewDidLoad()
    }

@IBOutlet public var myBackgroundView: UIView!
@IBOutlet public weak var myLabel: UILabel!

The nice thing about this approach (and I'm totally on-board with this use case) is that you can do the IBOutlet mapping in Interface Builder on the superclass, then switch the class of the Scene to the subclass, while retaining all of the mappings.

E.g.: SubclassedCustomViewController

import UIKit
import mymodule

class SubclassedCustomViewController: CustomViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        myBackgroundView.backgroundColor = UIColor.blueColor()
        myLabel.text = "My special subclass text"
    }
5

I realize that this question was posted a while ago, but since I just struggled with the same issue and finally came up with a solution, I figured I would still post my findings...

I understand the problem to be as follows (at least that's the one I solved):

How to have class A inherit from class B, with each class having its own XIB file with the some common IBOutlet properties? The goal being to be able to have the super class handle the actions related to the IBOutlets that are common to its subclass(es), while still being able to use Interface Builder to design the interface for the subclass(es).*

In order to do so:

  • Make the IBOutlet connections in the superclass from the superclass' XIB files
  • Make the IBOutlet connections in the subclass from the subclass' XIB files, with the same IBOutlet property names as in the superclass for the ones you need to inherit.
  • Delete the declaration of the IBOutlet variables in the subclass
0

See my answer here

But essentially hook your sub classes up to IBoutlets in the sub class just like you normally would, then create the super class, inherit from the subs and then paste the iboutlets into the super class. Your connections are still looking at the sub class, but that class is looking at the super class.

Not the answer you're looking for? Browse other questions tagged or ask your own question.