Reputation: 7200
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.
Upvotes: 0
Views: 894
Reputation: 1230
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.
Upvotes: 2
Reputation: 6427
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()
}
Upvotes: 0