0

I have UIViewController (first) which has tab bar at the bottom. I have next code in this controller:

let tabBarHeight = self.tabBarController?.tabBar.frame.size.height

It's working fine, but when I'm going from this first to next one (second) controller and then pressing Back button and returning to first, self.tabBarController is nil. Why does it happen? I have only one version, that stack of controllers is overcrowded.

How can I fix this? I need this height to calculate some value for constraint change in keyboardWillShow function.

UPDATE:

How do I call it:

// MARK: - Scroll view on keyboard show/hide
extension CommentariesController: UITextFieldDelegate {
    func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
           let keyboardHeight = keyboardSize.height
           let tabBarHeight = self.tabBarController?.tabBar.frame.size.height
           UIView.animate(withDuration: 1.0, animations: {
               self.newCommentViewBotConstraint.constant = -keyboardHeight + tabBarHeight!
               self.view.layoutIfNeeded()
           })
        }
    }

    // other code 
}

Update 2:

I can see tab bar. But it is nil.

Structure (with Show segues): tabbar -> navbar -> viewcontroller -> viewcontroller -> viewcontroller (first) -> viewcontroller (second).

Thanks

Vlad Pulichev
  • 2,784
  • 2
  • 14
  • 34
  • is it only happening sometimes?? Where `tabBarController` in nil in 'viewWillAppear` or `viewDidLoad` ?? – Bilal Jun 07 '17 at 10:11
  • @Bilal only in situation, that I have described. Here: extension CommentariesController: UITextFieldDelegate { func keyboardWillShow(notification: NSNotification) { – Vlad Pulichev Jun 07 '17 at 10:12
  • Have you tried calling it inside `keyboardWillShow`? That should be fine. If you try calling `self.tabBarController` before the ViewController is on the screen, it might return nil, which I think is your case here. – TawaNicolas Jun 07 '17 at 10:13
  • @TawaNicolas I always call it in keyboadWillShow :) – Vlad Pulichev Jun 07 '17 at 10:14
  • How are you going to the next view controller, are you pushing it. – Aravind A R Jun 07 '17 at 11:03
  • @AravindAR i use "show" – Vlad Pulichev Jun 07 '17 at 11:09
  • Ok then which viewcontroller is set as the root of your window?? – Aravind A R Jun 07 '17 at 11:09
  • @AravindAR tab bar controller. Structure : tabbar -> navbar -> viewcontroller -> viewcontroller -> viewcontroller (first) -> viewcontroller (second). Like this. I can see tab bar btw. Was a mistake in last comment – Vlad Pulichev Jun 07 '17 at 11:20
  • Ok thanks, I am trying on a demo project will let you know if I'm also facing the same issue. – Aravind A R Jun 07 '17 at 11:28
  • @AravindAR thanks you for your time – Vlad Pulichev Jun 07 '17 at 11:29
  • Between how are you adding notification observer to CommentariesController ? – Aravind A R Jun 07 '17 at 11:32
  • Most likely this happens when the controller has hidden, which causes the keyboard to disappear and it also causes the tab bar to be `nil`. – Sulthan Jun 07 '17 at 11:34
  • @Sulthan what do u mean? I come back to this controller. And in this controller I'm trying to get height. And I can see tab bar. Can u explain it again? Thanks you! – Vlad Pulichev Jun 07 '17 at 11:40
  • @AravindAR like always: NotificationCenter.default.addObserver(self, selector: #selector(CommentariesController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(CommentariesController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) – Vlad Pulichev Jun 07 '17 at 11:42
  • Ok. I tried out the above code on a sample project but I'm not getting self.tabBarController as nil. I'm sorry but I couldn't find anything that lead to this issue. – Aravind A R Jun 07 '17 at 13:27
  • @AravindAR can you please add answer with screenshot of the storybord?:) – Vlad Pulichev Jun 07 '17 at 13:29
  • @VladPulichev done – Aravind A R Jun 07 '17 at 13:39

2 Answers2

1

TabBar controller is set as the root and then navigation controller as tabBar's one of the item and the TestViewController as the root of that navigation controller. Then this TestViewController has a textfield to check the keyboardWillShow function and on tapping the UIButton - "button" new viewcontroller is pushed. On tapping back and again checking keyboardWillShow function self.tabBarController is not nil and I'm getting the correct height of tabBar inside that function

 NotificationCenter.default.addObserver(self, selector: #selector(TestViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)


    extension TestViewController {
    func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            let keyboardHeight = keyboardSize.height
            let tabBarHeight = self.tabBarController?.tabBar.frame.size.height
            UIView.animate(withDuration: 1.0, animations: {
                print("tabBarheight - \(tabBarHeight)")

            })
        }
    }

}
Aravind A R
  • 2,576
  • 1
  • 10
  • 23
0

On iOS >= 8.0, the tabbar height is always 49 pt (see What's the height of a UITabBar on iOS 8, iOS 9 and iOS 10?).

If you need some complex UI use case to solve when the tabbar is not accessible, just put that number into a constant and use that, e.g.:

let tabbarHeight: CGFloat = 49.0

or, save the value to a variable, e.g.

var tabbarHeight:

viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated: animated)

    self.tabbarHeight = self.tabBarController!.tabBar.frame.size.height
}
Sulthan
  • 118,286
  • 20
  • 194
  • 245