I\'m creating a custom navigation controller. I have something like this:
public class CustomNavigationController: UINavigationController {
// MARK: - L
UINavigationController
's implementation of init(rootViewController:)
probably calls self.init(nibName:bundle:)
which you haven't implemented so it throws the error.
You should override init(nibName:bundle)
in addition to the initializers you already override. init(nibName:bundle:)
is a designated initializer while init(rootViewController:)
is a convenience initializer.
I had this issue happen to users on iOS 12.4, so to do a workaround in my custom initializer I did something like this:
init(rootViewController: UIViewController, numberOfPages: Int) {
self.numberOfPages = numberOfPages
if #available(iOS 13.0, *) {
super.init(rootViewController: rootViewController)
} else {
super.init(nibName: nil, bundle: nil)
self.viewControllers = [rootViewController]
}
}
I basically initialize my class differently for every iOS version below 13. This does seem like the shortest solution.
While using custom navigation controller, we need to use override init
property of NavigationController
as-
class CustomNavigationController: UINavigationController {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
}
& in Appdelegate
class use -
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let vc = ViewController(nibName: "ViewController", bundle: nil)
let navi = CustomNavigationController(rootViewController: vc)
window?.backgroundColor = .white
window?.rootViewController = navi
window?.makeKeyAndVisible()
return true
}
}
As per Apple Document - To simplify the relationships between designated and convenience initializers, Swift applies the following three rules for delegation calls between initializers:
Rule 1 A designated initializer must call a designated initializer from its immediate superclass.
Rule 2 A convenience initializer must call another initializer from the same class.
Rule 3 A convenience initializer must ultimately call a designated initializer.
A simple way to remember this is:-