cfischer
cfischer

Reputation: 24912

Crazy behaviour with UIViewController inits in Swift

I'm trying to add simple initialiser to a UIViewController in Swift. So far it has been very frustrating...

First I tried adding it as a convenience init:

class ImageViewController: UIViewController {

    var model: UIImage

    convenience init(model: UIImage){

        self.init(nibName: nil, bundle: nil)
        self.model = model

    }
....

If I do this, the compiler forces me to implement required init(coder aDecoder: NSCoder). I checked the definition of the UIViewController class and there's no such requirement, but anyway.

To make things worse, the compiler complains that the self.init(nibName: nil, bundle: nil) call has an erroneous extra argument in bundle:. Again, I checked the class definition and the initialiser signature requires both parameters.

So I decided to make it a designated init. It's not what I want, as I don't want to lose all the superclass initialisers.

Now it seems to be happy with the self.init(nibName: nil, bundle: nil) call, but it still insists that I implement init(coder aDecoder: NSCoder).

Any ideas of what's going on? I can't make head or tails of this...

Upvotes: 2

Views: 862

Answers (2)

ma11hew28
ma11hew28

Reputation: 126377

If you don't want the model property to be optional, don't make it optional. Sure, it's a bitch to have to implement initWithCoder:, but it's better to have rock-solid, secure code.

class ImageViewController: UIViewController {
    var model: UIImage

    init(model: UIImage) {
        self.model = model
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

This ensures that the only way an instance of ImageViewController can be created is by calling initWithModel: and therefore guarantees that model will always have a nonoptional value.

Maybe in the future, Apple will add a convenient way of doing this, but for now, I must sacrifice convenience for control.

Upvotes: 1

Martin R
Martin R

Reputation: 539805

The error messages are indeed confusing, but I think they come from the fact that if the model property has no default value then the required initializers are no longer inherited from the superclass. With an optional (or implicitly unwrapped optional) property (which has the default value nil) your code compiles:

class ImageViewController: UIViewController {

    var model: UIImage!

    convenience init(model: UIImage) {
        self.init(nibName: nil, bundle: nil)
        self.model = model
    }
}

Upvotes: 3

Related Questions