NavigationBar titleView jump on viewWillAppear - swift

I create NavTitleView.xib(added in this xib 2 label "TITLE" and "SUBTITLE") and also create for this xib swift file.
Then i want use this xib as navigationItem.titleView
in viewWillAppear i write this code
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
let titleView = NSBundle.mainBundle().loadNibNamed("NavTitleView", owner: self, options: nil)[0] as! NavTitleView
titleView.TitleLabel.text = "My beautiful title"
titleView.SubtitleLabel.text = "My beautiful subtitle"
self.navigationItem.titleView = titleView
}
All works great! But when my view appear - this NavTitleView make jump from left side to center! I don't understand why? How to fix it?

if you have rightBarButtonItem set up, try calling self.navigationItem.rightBarButtonItem = UIBarButton again inside viewWillAppear

Related

UIKit: Adding text to NavigationBar

I'm diving into UIKit and feel some misunderstanding after using SwiftUI. By following course from Paul Hudson there is some challenges in the end of the project. One of this it's try showing the player’s score in the navigation bar. I try to solve this case but closest solution that I found from Apple's documentation it's:
let scoreButton = UIBarButtonItem(title: NSLocalizedString("Score: \(score)", comment: ""),
style: .done,
target: self,
action: nil)
navigationItem.rightBarButtonItem = scoreButton
But I think adding Button instead of simple Text is unnecessary, I don't need button behavior. Trying to add UITextView() to NavigationBar from storyboard did't work out...
Question: how to add text(better programmatically) to Navigation Bar? something like .toolbarItem with ToolbarItemPlacement: .navigationBarTrailing in SwiftUI. Is it possible or it's a UIKit restriction using only rightBarButtonItem?
You can use titleView property to show a text in the NavigationBar
override func viewDidLoad() {
super.viewDidLoad()
let view = UIView()
view.addSubview(titleLabel)
view.addSubview(scoreLabel)
navigationItem.titleView = view
}
I found solution how to add text to NavBar and yes it's restriction of UIKit thats you have to use UIBarButtonItem
let scoreView = UILabel()
scoreView.text = "Score: \(score)"
let scoreButton = UIBarButtonItem(customView: scoreView)
navigationItem.rightBarButtonItem = scoreButton

Navigation Controller inside Tab Bar Controller is showing but Right Bar Button not showing - Swift 4 - Programmatic Approach

I'm still new to iOS Dev.
Goal: Create an iOS App with Navigation Bar (with .add as right bar button) at the top and Tab Bar at the bottom screen using Programmatic approach (not using storyboards and xib)
So I did almost everything here: https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/CombiningViewControllers.html
But apparently it doesn't work (maybe because it is old? idk) and I'm also not comfortable configuring the App Delegate yet.
So what I have are these:
CompanyViewController as UIViewController
AssessmentViewController as UIViewController
TabViewController as UITabBarController, UITabBarControllerDelegate
I tried putting navigation controllers inside each VCs (navigationBar when I tap Tab Bar Items, which is expected - but the Title and Right Bar Button is NOT showing
I tried creating Swift file UINavigationController and named it NavigationViewController then added it to the TabViewController -> viewControllers but what happened was it was added to the tab bars at the bottom of the screen so it's not what I need and it looks like an ordinary tab not a navigation bar.
This is the last one I tried which displays Navigation Controller with its title but not its right bar button...
class TabViewController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let tabOne = CompanyViewController()
let tabOneBarItem = UITabBarItem(title: "Company", image: .none, tag: 1)
tabOne.tabBarItem = tabOneBarItem
let tabTwo = AssessmentViewController()
let tabTwoBarItem2 = UITabBarItem(title: "Assessment", image: .none, tag: 2)
tabTwo.tabBarItem = tabTwoBarItem2
self.viewControllers = [tabOne, tabTwo]
setUpNavigation()
}
func setUpNavigation() {
navigationItem.title = "Company Assessmentz"
self.navigationController?.navigationBar.barTintColor = colorLiteral
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor:colorLiteral]
self.navigationController?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(selectorX))
}
#objc func selectorX() { }}
replaced this:
self.navigationController?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(selectorX))
to this:
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .camera, target: self, action: #selector(selectorX))

Using UINavigationItem on UITabBarController

I have a project with a UITabBarController and a couple of views. Sort of like this:
In this project, the tab bar controller is called by tapping the Tab button on the UIViewController. I would like to get rid of the back button with "Title", and replace it with an "X" icon. When tapped, the "X" icon would dismiss the UITabBarController and return to the caller. I do this all of the time on UINavigationController using a UINavigationItem, but that does not appear to work in this situation. I drag the UINavigationItem to the view and it allows it, but it does not show up on the view and any UIBarButtonItem that I drag and drop on it do not appear.
Is there a way to actually do this? I'd even be ok with leaving the existing back button as it is and just getting rid of "Title"
I figured it out right after posting the question. Just a bit more research is all it took.
To fix this, add the following to the UITabBarController code.
override func viewDidLoad() {
super.viewDidLoad()
let buttonImage = UIImage(named: "back")
let leftButton = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(dismissTabBar))
leftButton.tintColor = UIColor.black
self.navigationItem.leftBarButtonItem = leftButton
}
#IBAction func dismissTabBar() {
self.navigationController?.popToRootViewController(animated: true)
}
This gives me a black back button with my image. When I tap it, it brings me back to the calling 'UIViewController.

Programmatically create a navigation view

So I'm trying to create an app but I'm trying to avoid the use of storyboards. Hence just using swift files along with XIB files.
I have worked a little with Navigation controllers before but not enough I guess. So far I have this:
In AppDelegate I have:
let homeVC = HomeViewController()
let rootVC = UINavigationController(rootViewController: homeVC)
window!.rootViewController = rootVC
window!.makeKeyAndVisible()
My view currently is entirely empty, but with the basic "View" screen that comes with creating a new XIB file. I've set the size of that to freeform, and all other things like Top Bar, Status Bar are Inferred.
In my HomeViewController.swift I have:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let nib = UINib(nibName: "HomeView", bundle: nil)
let objects = nib.instantiateWithOwner(self, options: nil)
self.view = objects[0] as! UIView;
print(self.navigationController)
// customize navigation bar
let settingsImage = UIImage(named: "settingsWheelBlack.png")
let settingsNavItem = UIBarButtonItem(image: settingsImage, style: UIBarButtonItemStyle.Plain, target: nil, action: Selector("selector"))
let addStuffItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: nil, action: Selector("selector"))
self.navigationController?.navigationItem.title = "Home"
self.navigationController?.navigationItem.leftBarButtonItem = settingsNavItem
self.navigationController?.navigationItem.rightBarButtonItem = addStuffItem
print(self.navigationController?.navigationBar)
print(self.navigationController?.navigationItem.title)
}
But when I run the application the navigation bar doesn't show up. Here's what I've tried besides what I currently have:
Add a Navigation Bar control to my XIB and connect an IB outlet to it. Also connect the IB outlet to the navigation item that already exists in the navigation bar control. Then set the title, and left and right buttons in that. Didn't work
Set the title and buttons in AppDelegate straight away for the rootVC defined above. Didn't work.
Any ideas what I'm missing?
I solved this after gathering some strength to read through tons of Apple docs. On this page I found this small piece of text:
In a navigation interface, each content view controller in the navigation stack provides a navigation item as the value of its **navigationItem** property. The navigation stack and the navigation item stack are always parallel: for each content view controller on the navigation stack, its navigation item is in the same position in the navigation item stack.
So I left my AppDelegate code as is and changed me viewDidLoad function to:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let nib = UINib(nibName: "EventsHomeView", bundle: nil)
let objects = nib.instantiateWithOwner(self, options: nil)
self.view = objects[0] as! UIView;
print(self.navigationController)
// customize navigation bar
let settingsImage = UIImage(named: "settingsWheelBlack.png")
let settingsNavItem = UIBarButtonItem(image: settingsImage, style: UIBarButtonItemStyle.Plain, target: nil, action: Selector("selector"))
let addStuffItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: nil, action: Selector("selector"))
// Each VC within a navigation controller has it's own navigationItem property that the underlying navigation controller uses to show in the navigationBar
self.navigationItem.title = "Home"
self.navigationItem.leftBarButtonItem = settingsNavItem
self.navigationItem.rightBarButtonItem = addStuffItem
}
And viola!

Changing navigation title programmatically

I have a navigation bar with a title.
When I double click the text to rename it, it actually says it's a navigation item, so it might be that.
I'm trying to change the text using code, like:
declare navigation bar as navagationbar here
button stuff {
navigationbar.text = "title"
}
That's not my code obviously, just showing how it would work.
So whenever I press the button, I want the title to change.
You change the title by changing the title of the view controller being displayed:
viewController.title = "some title"
Normally this is done in view did load on the view controller:
override func viewDidLoad() {
super.viewDidLoad()
self.title = "some title"
}
However, this only works if you have your view controller embedded in a UINavigationController. I highly recommend doing this instead of creating a navigation bar yourself. If you insist on creating a navigation bar yourself, you can change the title by doing:
navigationBar.topItem.title = "some title"
Try the following in viewDidLoad
self.navigationItem.title = "Your Title"
The code below works for me with Xcode 7:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "Your Title"
}
I found this to work:
navigationItem.title = "Title"
Swift 5.1
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "What ever you want"
}
and also if you will try to create Navigation Bar manually this code will help you
func setNavBarToTheView() {
let navBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 64.0))
self.view.addSubview(navBar);
let navItem = UINavigationItem(title: "Camera");
let doneItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.cancel, target: self, action: #selector(CameraViewController.onClickBack));
navItem.leftBarButtonItem = doneItem;
navBar.setItems([navItem], animated: true);
}
The correct answer for people using swift4 would be
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "Your Text"
}
Normally, the best-practice is to set the title on the UIViewController. By doing this, the UINavigationItem is also set. Generally, this is better than programmatically allocating and initializing a UINavigationBar that's not linked to anything.
You miss out on some of the benefits and functionality that the UINavigationBar was designed for. Here is a link to the documentation that may help you. It discusses the different properties you can set on the actual bar and on a UINavigationItem.
Just keep in mind:
You lose back button functionality (unless you wire it yourself)
The built-in "drag from the left-hand side to swipe back" gesture is forfeited
UINavigationController's are your friends.
If you have a NavigationController embedded inside of a TabBarController see below:
super.tabBarController?.title = "foobar"
You can debug issues like this with debugger scripts. Try Chisel's pvc command to print every visible / hidden view on the hierarchy.
Swift 3
I created an outlet for the navigation title bar item that comes with the navigation bar (from the Object Browser) in the storyboard. Then I sued the line below:
navigationBarTitleItem.title = "Hello Bar"
If you wanted to change the title from a child view controller of a Page View Controller that's embedded in a navigation controller, it would look like this:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.parent?.title = "some title"
}
If you have not created navigation bar in your view controller from storyboard this will work.
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Title"
}
If you have created navigation bar in your view controller from storyboard this will be helpful.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Title"
}
in viewDidLoad
navigationController?.navigationBar.topItem?.title = "Your Text"
This worked for me. Just connect an outlet to your nav bar and access the title through the topItem
navBar.topItem?.title = "Your Title Here"
In Swift 4:
Swift 4
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Your title"
}
I hope it helps, regards!
I prefer using self.navigationItem.title = "Your Title Here" over self.title = "Your Title Here" to provide title in the navigation bar since tab bar also uses self.title to alter its title. You should try the following code once.
Note: calling the super view lifecycle is necessary before you do any stuffs.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupNavBar()
}
}
private func setupNavBar() {
self.navigationItem.title = "Your Title Here"
}
Swift 5.1
// Set NavigationBar Title Programmatically and Dynamic
Note :
First add NavigationControllerItem to Your ViewController then goto their ViewController.swift file and Just Copy and Paste this in viewDidLoad().
navigationItem.title = "Your Title Here"
e.g.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Your Title Here"
}