我们在项目中根据需求经常会为一些控制器自定义一个导航栏,这时我们就需要在此类控制器显示时隐藏导航控制器默认的导航栏,不显示时显示导航控制器自己的导航栏,这样就会导致代码侵入到各个需要自定义导航栏的控制器中。那么怎么做可以节省这种频繁的操作呢?我这有两个方法。
首先都添加UINavigationControllerDelegate代理对象为self
class BaseNavC: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
}
第一种是在自定义的基类导航控制器中设置需要隐藏默认导航栏的控制器名单。
let needHiddenVCNames :[String] = ["xxx","xxx"]
extension BaseNavC: UINavigationControllerDelegate {
//导航控制器将要显示控制器时调用,名单中控制器隐藏导航栏,其他的控制器显示导航栏
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
print(type(of: viewController))
let name: AnyClass! = object_getClass(viewController)
let vcName = NSStringFromClass(name)
let vc = vcName.split(separator: ".").last
if needHiddenVCNames.contains(String(vc ?? "")){
self.setNavigationBarHidden(true, animated: true)
}else {
self.setNavigationBarHidden(false, animated: true)
}
}
}
第二种是建立一个隐藏导航栏的协议,在需要隐藏的控制器中遵循协议,即可达到相同效果
/// 遵循这个协议,可以隐藏导航栏
protocol HideNavigationBarProtocol where Self: UIViewController {}
extension BaseNavC: UINavigationControllerDelegate {
//导航控制器将要显示控制器时调用
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
if (viewController is HideNavigationBarProtocol){
self.setNavigationBarHidden(true, animated: true)
}else {
self.setNavigationBarHidden(false, animated: true)
}
}
}
好啦,这样我们就可以减少很多此类操作的代码冗余和管理。这里推荐第二种使用协议的方式隐藏导航栏,这样方便追踪到隐藏导航栏的代码控制,清晰代码阅读和理解。名单的方式不方便后面代码接手的人找到导航隐藏和显示的过程,还需要去维护名单的建设。