I recently came across this question and thought I'd post my own solution, for posterity, as I think its pretty light-weight and some may prefer it.
First, however you create your tab items (mine is a UITabBarController
subclass that I pass my child controllers into) - set the tab item title to an empty string.
(Of course, this solution is also specific to the OP scenario where you have a TabbarController
with an embedded Nav Controller - which is relatively common).
As you probably know, setting the UIViewController's title will cause the related tab item to pick up the title.
In order to have a UIViewController title without setting the Tab item title -- add a new UILabel to the view controller's Navigation Item Title View.
I wound up creating an extension on UIViewController
like so:
extension UIViewController {
func addNavItemTitle(resourceString: String, textColor: UIColor = UIColor.white) {
// Add title view ~ allows overriding title w/out showing it on tabBarItem
let titleLabel = UILabel()
titleLabel.text = NSLocalizedString(resourceString)
titleLabel.textColor = textColor
titleLabel.font = UIFont.viewTitle
titleLabel.sizeToFit()
self.navigationItem.titleView = titleLabel
}
}
Customize your fonts and colors however you like. Let the label size itself so you don't have to measure it or set its frame here.
I also prefer to use localized strings vs. setting the strings directly.
Now, in any tab child controller, in order to set my view controller title while not picking up a Tab item title - I just call addNavItemTitle(resourceString: "example.title")
A good place is in viewDidLoad
You may have also noticed that my call to NSLocalizedString
is missing an argument. That's because I tend to use the same string for the comment as the resource string. So I've created a global function to simplify the call without repeating the string.
Like so:
public func NSLocalizedString(_ key: String) -> String {
return NSLocalizedString(key, comment: key)
}