I would like to add title to my UIViewController:
I have tried
self.navigationController.navigationItem.title
self.navigationController.title
self.title
Sometimes, solution 1 work, sometimes solution 2 work, sometimes solution 3 works.
Can any expert tell me the different between them?
title is a property of UIViewController.
A localized string that represents the view this controller manages.
Set the title to a human-readable string that describes the view. If
the view controller has a valid navigation item or tab-bar item,
assigning a value to this property updates the title text in those
objects.
self.navigationController is a UINavigationController that manages the stack of viewControllers that your viewController is in. UINavigationController is a subclass of UIViewController, so self.navigationController.title is the title of the UINavigationController.
self.navigationItem.title:
The navigation item’s title displayed in the center of the navigation
bar. The default value is nil. When the receiver is on the navigation
item stack and is second from the top—in other words, its view
controller manages the views that the user would navigate back to—the
value in this property is used for the back button on the top-most
navigation bar. If the value of this property is nil, the system uses
the string “Back” as the text of the back button.
So, in practice, you should set the title of your ViewControllers. iOS will copy this title to the navigation item or tab bar item and display this title on the Navigation Bar if your ViewController is managed by a UINavigationController, it will use that text for the Back Button when you push to another ViewController, and it will display it in the tab bar if your ViewController is managed by a UITabBarController.
I create a demo to explain them:
You see, my vc1 is yellow-gray color embed in a navigation controller,my vc2 is light-green color embed in a navigation controller too, the two navigation controller is all manage by a tabbar controller .
In ViewController.swift(it is vc1), if I set self.title:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "vc1's title"
}
}
In ViewController2.swift(it is vc2):
import UIKit
class ViewController2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "vc2's title"
}
}
The result is the tabbar title and navigation title all set:
If I set self.navigationController?.title:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// self.title = "vc1's title"
self.navigationController?.title = "vc1's nav title"
}
}
The result is tabbar title is set:
If I set self.navigationItem.title:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// self.title = "vc1's title"
//self.navigationController?.title = "vc1's nav title"
self.navigationItem.title = "vc1's navItem title"
}
}
The result is navigation title is set:
Related
I have a UIViewController A, embedded in a UINavigationViewController that pushes another view controller B on some action. Given the UIViewController.title of A is set to say "VC A", when B is displayed the back button has the title "< VC A" as expected. However if I were to set the title of B AFTER its viewDidLoad, the back button title gets changed to "< Back". If the title were to be set in viewDidLoad the back button title remains as "< VC A". Any thoughts on how I can set the title of B without it effecting the back button?
class ViewControllerA: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "VC A"
}
func doSomething() {
// Instantiate ViewControllerB
navigationController?.pushViewController(viewControllerB, animated: true)
}
}
class ViewControllerB: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "VC B" // Works as expected
}
func doSomething() {
title = "VC B" // Causes the back button title to change to Back from VC A
}
}
I can create a custom back button with the title of the previous view controller in the navigation stack as a workaround but I'm rather curious as to why this occurs in the first place and a possible simpler work around.
I have multiple view controllers embedded inside a navigation controller. I have an option that changes the language of the user interface. When user chooses French, the user interface should update itself with French language. All elements are updated with French as I expected, except the button that takes user back to the previous view controller (as you can see in the screenshot - "List of Events").
This is the function I call to update UI :
func updateView() {
DispatchQueue.main.async {
// CurrentSelection.LanguageUI holds a reference to currenly selected language object
navigationItem.title = CurrentSelection.languageUI.event_singular
navigationController?.title = CurrentSelection.languageUI.listOfEvents <<- this line doesn't work
}
}
The navigationController?.title holds "List of Events" string and the assignment statement seems to work. It just that the UI isn't updated with the new title value. Where am I doing wrong?
It's the previousVC that decides what it's own back button will be.
So set this on the previousVC in viewDidLoad
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Back title" style:UIBarButtonItemStylePlain target:nil action:nil];
If this isn't set then the back button will be the .title of the previous VC.
-
In your situation you should have some kind of language change notification that the previous VC can listen for and know to update its own title.
One way to do it is to implement UINavigationControllerDelegate and set the back bar button item there:
class YourViewController: UIViewController, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
}
// MARK: - Navigation controller delegate
public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
let item = UIBarButtonItem(title: "Custom title", style: .plain, target: nil, action: nil)
viewController.navigationItem.backBarButtonItem = item
}
}
Something to be aware of is that this needs to be implemented in the view controller which pushes the next view controller. So you'll be changing the back bar button item of the view controller that willShow.
Those view controllers in the navigation stack won't change atomatically.
So you have to use Notification center and add observers to the previous view controllers and change the Title of the navigation bar with selected language when it is called.
When language is changed you have to post the change.
Then it will change the title to french so does the back button will
change.
I created a custom search bar and embedding it in the navigation bar, it appears but after I push another view controller, the search bar does not get replaced with the title of the pushed view controller. The search bar stays persistent throughout all views, instead of getting replaced with a title. Perfect example is Instagram search tab, you search for a person and click on the cell, their profile is pushed and the search bar is replaced with the custom title, back button, etc.
First VC
self.customSearchBar.tag = 4
self.navigationController?.view.addSubview(customSearchBar)
Second VC
if let nav: UINavigationController = self.navigationController {
if let searchBar = nav.view.viewWithTag(4) {
searchBar.removeFromSuperview()
}
}
You shouldn't place the searchbar inside the navigationcontroller view as this view is the same instance on all pushed viewcontrollers.
Add the searchbar to the the depending view controllers ui.
To add a searchbar on navigationBar, this is the way.
self.navigationController?.navigationBar.addSubview(customSearchBar)
To remove it when you push it to other viewController. Write the following code in the secondVC that is pushed inside it's viewDidLoad() function. Also, set the tag of customSearchBar to any number (TAG)
if let nav: UINavigationController = self.navigationController {
let bar: UINavigationBar = nav.navigationBar
if let searchBar = bar.viewWithTag(TAG) {
searchBar.removeFromSuperview()
}
}
In the question, the customSearchBar is added to self.navigationController.view. To remove it, you can do the following:
if let nav: UINavigationController = self.navigationController {
if let searchBar = nav.view.viewWithTag(TAG) {
searchBar.removeFromSuperview()
}
}
Edit:
Adding and removing a UIViewController's view as a subview of other UIViewController
// for adding
let viewController: ViewController = ViewController()
self.addChildViewController(viewController)
self.view.addSubview(viewController.view)
viewController.view.bounds = self.view.bounds // better to use autolayout here
viewController.didMove(toParentViewController: self)
// for removing
if let vc = self.childViewControllers.last {
vc.willMove(toParentViewController: nil)
vc.view.removeFromSuperview()
vc.removeFromParentViewController()
}
I want to change the navigation's title of a view, which is related to a Tab Bar Controller, which is related to a Navigation Controller (see the picture)
I don't know how to do that.
With a basic view, I just need to do that in the ViewController.swift :self.title="test"
But here, this line changed the tab bar's title, but I want to change the navigation's title.
Main.Storyboard :
On Swift 3, in the UIViewController, override your viewDidAppear method and add this code snippet:
if let tabController = self.parent as? UITabBarController {
tabController.navigationItem.title = "My Title"
}
Use need to use this property:
self.navigationItem.title = "someTitle"
According to Apple best practices you should not have a tab bar controller contained inside of a navigation controller, rather you should have the view controller for each tab that requires one to be inside of it's own navigation controller.
There are various issues that can arise from having a tab bar controller contained within a navigation controller.
When implemented according to their standards you can set the title using self.title
An app that uses a tab bar controller can also use navigation controllers in one or more tabs. When combining these two types of view controller in the same user interface, the tab bar controller always acts as the wrapper for the navigation controllers.
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/CombiningViewControllers.html
Embed UINavigationController in your storyboard and put:
navigationBar.topItem.title = "Nav title"
I also had difficulty to change a navigation bar title of a child view controller. The solution was:
#IBOutlet weak var navigationBar: UINavigationBar!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.topItem!.title = "Pickup Address"
}
For Swift 3+
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.title = "Title"
}
I've created a tab bar controller and embedded several view controllers in it. I then try to set a specific tab bar item in a corresponding swift file for that view. Problem is that I am changing the item by overriding the "viewDidLoad" function. So it only updates after the user has touched that item. What be a better approach to changing storyboard tab bar items using swift?
create a subclass of UITabBarController
set this custom class of your TabBarController
now you override UITabBarController ViewDidLoad Method
there you can access all the TabItems and change their text/images
before a ViewController get loaded.
class CustomTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let allItems:[AnyObject] = self.tabBar.items!
var item1:UITabBarItem = allItems[0] as! UITabBarItem
var item2:UITabBarItem = allItems[1] as! UITabBarItem
item1.image = UIImage(named: "menu#2x.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
item2.image = UIImage(named: "play#2x.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
}
}
in custom class the code should be like as above...
you can set selectedState Image as well....
here is the result..