简体   繁体   中英

Inheriting from UINavigationController in Swift

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.

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.

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()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM