1
votes

I'm using XLForm, which has a class XLFormDescriptor, which needs to be initialized with init(title: String).

The title I want to use is the return value of my current class's name function (class-level properties aren't a feature yet).

Putting this at a class level, the code to set it up looks like this:

let settingsForm = XLFormDescriptor(title: self.name())

But this gives the error:

'PanelController -> () -> PanelController!' does not have a member named 'name'

Putting this at the top of the class's init call looks like this:

let settingsForm: XLFormDescriptor

override init() {
    self.settingsForm = XLFormDescriptor(title: self.dynamicType.name())

    super.init()
}

And doing that gives this error:

'self' used before super.init call

Putting it after super.init() gives this error:

Property 'settingsForm' not initialized at super.init call

Any ideas how I can possibly do this?

EDIT: A workaround is to do this:

let settingsForm = XLFormDescriptor(title: "")

override init() {
    super.init()
    self.settingsForm = XLFormDescriptor(title: self.dynamicType.name())
}
1

1 Answers

1
votes

In swift, self is not available until all class properties have been initialized. There's a check at compilation time for that.

So if you have a class with properties, inherited from another class:

class A {
    var prop1: Int
    init(val1: Int) {
        self.prop1 = val1
    }
}

class B : A {
    var prop2: String
    override int(val1: Int, val2: String) {
        // First initialize properties of this class
        self.prop2 = val2

        // Next call a superclass initializer
        super.init(val1: val1)

        // From now on, you can use 'self'
    }
}

you cannot use self until all (non optional) class properties have been been initialized and a superclass initializer has been invoked (if the class is inherited).

If you initialize a property inline, like this:

let settingsForm = XLFormDescriptor(title: self.name())

you are explicitly using self before the class instance has been properly initialized - that's the reason of the compilation error.

The solution you found yourself is not a workaround, but the right way of doing it. You first initialize the property with a value not referencing self, then once the class has been initialized, you assign that property a new value.

Note that this is the only case where you are allowed to assign a new value to an immutable property, as long as it is done from within an initializer.

For a better understanding of how initialization works, I recommend reading the corresponding documentation: Initialization