Call methods from Swift initializer

declare it as an implicitly unwrapped optional

class MyClass : NSObject {
    var myProperty: String!

    init() {
        super.init()
        self.setupMyProperty()
    }

    func setupMyProperty() {
        self.myProperty = "x"
    }
}

page 499 of "The Swift Programming Language" manual


You can't use self until your instance's memory is fully initialized (at which point you can't set constant properties anymore), so the order in which your designated initializer has to do things is:

  1. initialize all properties added by this class
  2. call superclass initializer (if there is a superclass)
  3. now you can use self, call methods, etc

I'm not sure if there's a good workaround for the case of a constant property. One alternative would be to declare the property as an implicitly unwrapped optional, so it's initially set to nil:

class MyClass {
    var myProperty: String!
    init() {
        super.init() // only if you actually have a superclass, and make sure this does not use `myProperty`
        self.setupMyProperty()
    }

    func setupMyProperty() {
        myProperty = "x"
    }
}

Be careful with this, it loses a bit of type safety, as myProperty can now be nil, and if it is when you try to access it, it will lead to a runtime error. So only do this if you're sure it'll be initialized by all your designated initializers, not be used by anything called before setupMyProperty() in the initializer chain (e.g. when a superclass initializer calls a method you override that accesses myProperty), and never set to nil explicitly.

Also, cf. the docs, especially the section on Class Inheritance and Initialization for the whole call-order stuff I explained above.


Does setupMyProperty need to access self? If not, you can achieve this with a class method:

class MyClass: NSObject {
    let myProperty: String

    init() {
        myProperty = MyClass.setupMyProperty()
        super.init()
    }

    class func setupMyProperty() -> String {
        return "foo"
    }
}

Try putting setupMyProperty() in a constant. Then it is there before you initialise and you can call it from init(). You can even access parameters as follows:

class MyClass {
    var myProperty: String
    let setupMyProperty : (String) -> (void) = { 
        param in
        self.myProperty = param
    }

    init(x: String) {
    // removed redundant line: super.init()
        self.setupMyProperty(x)
    }
}

Tags:

Swift