0

I have a class that extends UINavigationController.

class MyNavigationController: UINavigationController {
    var reservationId: Int
    var blankViewController: BlankViewController

    init(clientId aClientId: Int, reservationId aReservationId: Int) {

        blankViewController = BlankViewController()

        clientId = aClientId
        reservationId = aReservationId

        super.init(rootViewController: blankViewController)
    }

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

This is doing things by the book. My designated initializer is calling super class designated initializer. But the app crashes at run time with this message:

fatal error: use of unimplemented initializer 
'init(nibName:bundle:)' for class 'MyiOSApp.MyNavigationController'

Through trial and error I made the problem go away by doing this instead.

init(clientId aClientId: Int, reservationId aReservationId: Int) {

    blankViewController = BlankViewController()

    clientId = aClientId
    reservationId = aReservationId

    super.init(nibName: nil, bundle: nil)
}

But init(nibName: nil, bundle: nil) is not a designated initializer of the immediate super class. Technically this should not even compile. So I am super confused. What specific rule was I violating with the first code? And if indeed I was breaking some rule why did the compiler not catch if it?

One potential explanation is that init(nibName:, bundle:) is a required initializer. But that explanation has problems. From what I can see init(nibName:, bundle:), init(rootViewController:) and init?(coder:) are not marked as required in the documentation or the source code view in Xcode. For some reason the compiler thinks that init?(coder:) is required but not so for the other init methods. All of this is very strange.

Edit: many of you are posting answers saying how to get this to work. My question is not about that. I can already get this to work as I have noted as much in my question. My question is about Swift initializer rules, and what I may be violating.

2
  • @Paulw11 the crash was not in init(coder). Please see the crash error message. Thanks. Commented Jun 29, 2017 at 14:04
  • 3
    You didn't implement the other required initialiser - init(nibName, bundle) - this is required by UIViewController Commented Jun 29, 2017 at 14:05

2 Answers 2

2

Your subclass will work if you override init(nibName:,bundle:) as well.

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

You will also have to provide default values for your properties.

Sign up to request clarification or add additional context in comments.

1 Comment

My question was not about how to somehow get this to work. It was about Swift initializer rules and what specific rule I may have been breaking. init(nibName:, bundle:) is not marked as required. The compiler doesn't think so either. So why do I have to implement it?
0

When you initialize any controller from storyboard it is required to implement

required init?(coder aDecoder: NSCoder) {}

and when you intialize controller manually allocating and intialize, you have to tell name of nib file name along with bundle name. for ref.

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)   {
        print("init nibName style")
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

This is good practice to have this init method

convenience init() {
    self.init()
}

1 Comment

init(nibName:, bundle:) is not marked as required. The compiler doesn't think so either.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.