iOS中navigationBar在keyboard出现时自动隐藏问题的处理

1、问题背景

在研究使用IQKeyBoardManager来处理键盘的弹出和放下等一些列事件的时候,页面使用的是UITableView,并在cell中绘制了多个文本输入框。由于项目是基于UINavigationController建立的,当键盘弹出时发现navigationBar 被自动隐藏了。等到键盘放下后navigationBar却没有像期望的那样重新回到当初的位置。第一感觉是不是使用了IQKeyBoardManager,而IQKeyBoardManager在处理键盘遮挡的时候更改了navigationbar的位置,照着这个想法随便研究了一下IQKeyBoardManager。

2、IQKeyBoardManager 设计思想及加载过程

它继承自NSObject,设计的方案是作为一个单例来加载,并且实现了NSObject 的类方法 load 来完成初始化,由于他采用的机制是将Manager作为键盘、设备方向相关事件的观察者,并且基于响应者当前界面的响应者链完成了相关控件的管理。

3、问题的最终确诊及解决方案

各种尝试更改IQKeyBoardManager在处理键盘弹出等事件相关方法都无果后,做了个移除IQKeyBoardManager的测试。结果发现navigationbar依然会被隐藏,经过一阵眩晕后发现原来NavigationController的在IOS8之后新增了如下属性,闲时还是得多读书呀……

/// When the keyboard appears, the navigation controller's navigationBar toolbar will be hidden. The bars will remain hidden when the keyboard dismisses, but a tap in the content area will show them.
    @available(iOS 8.0, *)
    open var hidesBarsWhenKeyboardAppears: Bool

    /// When the user swipes, the navigation controller's navigationBar & toolbar will be hidden (on a swipe up) or shown (on a swipe down). The toolbar only participates if it has items.
    @available(iOS 8.0, *)
    open var hidesBarsOnSwipe: Bool

    /// When the UINavigationController's vertical size class is compact, hide the UINavigationBar and UIToolbar. Unhandled taps in the regions that would normally be occupied by these bars will reveal the bars.
    @available(iOS 8.0, *)
    open var hidesBarsWhenVerticallyCompact: Bool

    /// When the user taps, the navigation controller's navigationBar & toolbar will be hidden or shown, depending on the hidden state of the navigationBar. The toolbar will only be shown if it has items to display.
    @available(iOS 8.0, *)
    open var hidesBarsOnTap: Bool

看第一个属性的注释,内心有一种放完炮就走的感觉,还好他留下了能解决问题的人,于是将希望寄托在了hidesBarsOnTap属性上。
单纯的通过在keyboard show和hidden时设置hidesBarsOnTap的true和false并没有完美的解决我的问题。随后增加了navigationbar显示和隐藏的监听。
最终解决方案的代码如下:

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.isNavigationBarHidden = false
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardHidden(notify:)), name:NSNotification.Name.UIKeyboardDidHide , object:nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow(notify:)), name:NSNotification.Name.UIKeyboardDidShow , object:nil)
        navigationController?.navigationBar.addObserver(self, forKeyPath: "hidden", options: NSKeyValueObservingOptions.new, context: nil)
    }
        
override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        navigationController?.hidesBarsWhenKeyboardAppears = false
        navigationController?.hidesBarsOnSwipe = false
        navigationController?.hidesBarsWhenVerticallyCompact = false
        navigationController?.hidesBarsOnTap = false        
    }
   
override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidHide, object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
        navigationController?.navigationBar.removeObserver(self, forKeyPath: "hidden", context: nil)
    }
    
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        if keyPath == "hidden",change != nil {
            let flag:Bool = change![NSKeyValueChangeKey.newKey] as! Bool
            if flag {
               self.navigationController?.hidesBarsOnTap = true
            }else{
               self.navigationController?.hidesBarsOnTap = false
            }
        }
        
    }
    
@objc func keyboardHidden(notify:Notification){
        
        self.navigationController?.hidesBarsOnTap =  navigationController?.isNavigationBarHidden == true ? true:false
    }
    
@objc func keyboardShow(notify:Notification){
        self.navigationController?.hidesBarsOnTap = true
    }

目前的解决方案还不是很完美,欢迎各位留言指正。

你可能感兴趣的:(iOS中navigationBar在keyboard出现时自动隐藏问题的处理)