如何创建带自定义初始化的UINavigationController类并解决初始化报错?
你遇到的问题其实是Swift初始化规则和UINavigationController初始化链共同导致的,咱们一步步拆解:
初始问题:未实现指定初始化器崩溃
你最初的代码自定义了一个带User属性的NavigationController,但只实现了自己的初始化器和init(coder:):
class NavigationController: UINavigationController { private let user: User init(user: User, rootViewController: UIViewController) { self.user = user super.init(rootViewController: rootViewController) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
运行时崩溃是因为UINavigationController的init(rootViewController:)是便捷初始化器,它内部会调用父类的指定初始化器init(nibName:bundle:)。而你的子类没有实现这个指定初始化器,系统找不到对应的实现就抛出了崩溃。
尝试修复后的编译器错误
当你添加了override init(nibName:bundle:)后:
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) }
编译器报错Property 'self.user' not initialized at super.init call,这是因为Swift要求所有非可选的存储属性必须在调用super.init之前完成初始化,而这个初始化器里完全没处理user属性,自然过不了编译。
不使用隐式解包可选的解决方案
要解决这个问题,我们需要调整初始化逻辑,确保所有初始化路径都能正确初始化user,同时遵循Swift的初始化规则:
class NavigationController: UINavigationController { private let user: User // 自定义初始化器:调用父类的指定初始化器,而非便捷初始化器 init(user: User, rootViewController: UIViewController) { self.user = user // 先调用父类的指定初始化器 super.init(nibName: nil, bundle: nil) // 手动设置根视图控制器 self.viewControllers = [rootViewController] } // 禁用Storyboard/XIB初始化路径 required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented - 请使用init(user:rootViewController:)初始化") } // 禁用通过nib/bundle的初始化路径 override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { fatalError("init(nibName:bundle:) has not been implemented - 请使用init(user:rootViewController:)初始化") } }
为什么这样可行?
- 遵循初始化规则:自定义初始化器先初始化
user属性,再调用父类的指定初始化器init(nibName:bundle:),满足Swift对初始化顺序的要求。 - 手动设置根视图:因为不再调用父类的便捷初始化器
init(rootViewController:),所以我们手动给viewControllers赋值来设置根视图控制器,效果和原代码一致。 - 禁用不需要的初始化路径:把其他两个指定初始化器都设置为抛出错误,确保外部只能通过我们自定义的初始化器创建实例,避免出现
user未初始化的情况。
这样既不用把user改成隐式解包可选类型,也能解决初始化时的崩溃和编译错误。
内容的提问来源于stack exchange,提问作者user11497206
相关产品推荐
相关产品推荐

