Adding a NavigationBar to UITableViewController programmatically? - iphone

I am trying to create a uitableviewcontroller as a modal viewcontroller to edit some settings. I am creating the tableviewcontroller in code and the thing i am struggling with currently is how to correctly add a navigation bar to the controller which will have a "Done" button on it that:
a) doesnt appear on top of the tableview and
b) does not scroll with the tableview??
This happens when i add the navbar to the contoller with:
[self.view addSubview:navigationBar];
This adds a navbar to the controller which goes on top and obscures the tables first row and also scrolls with the view?
I also thought about simply using a uiviewcontroller with a separate tableview however i like the funcitonality of automatically scrolling the tableview when editing a textfield that the tableviewcontroller gives you. Just cant figure how to setup this navbar??
thx

Just create UINavigationcontroller as the modal viewcontroller, and add the tableview as its root view controller.

Use Navigation controller as modalviewController(as suggested in the other answer). Here is the code:
UINavigationController *Controller = [[UINavigationController alloc] init];
//LoginViewController is a sub class of UITableviewController
LoginViewController *controller = [[LoginViewController alloc] init];
Controller.viewControllers=[NSArray arrayWithObject:controller];
[self presentModalViewController:Controller animated:YES];
[controller release];
[Controller release];

In Swift:
AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
/*
#1. Instantiate a navigation controller and add the table view controller
as a child view controller.
*/
let navigationController = UINavigationController()
// Instantiate your desired ViewController
let storyboard = UIStoryboard(name: UIStoryboardName.Main.rawValue, bundle: nil)
let tableViewController = storyboard.instantiateViewControllerWithIdentifier("TableViewControllerID")
navigationController.addChildViewController(tableViewController)
/*
#2. Then we set the title of the navigation bar and add two bar button items.
*/
// We set the title of the navigation bar.
tableViewController.navigationItem.title = "My Title"
// Create left and right button for navigation item.
let leftButton = UIBarButtonItem(title: "Save", style: UIBarButtonItemStyle.Plain, target: tableViewController, action: "saveButtonClicked:")
let rightButton = UIBarButtonItem(title: "Right", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
// Create two buttons for the navigation item.
tableViewController.navigationItem.leftBarButtonItem = leftButton
tableViewController.navigationItem.rightBarButtonItem = rightButton
/*
#3. To finish we set the root view controller with the navigation controller.
*/
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
TableViewController.swift
// Method called when the user clicks on the Save bar button item.
func saveButtonClicked(sender: UIBarButtonItem) {
// Do something.
print("Save bar button item has been clicked!!!")
}

Related

Display title on modally presented view in Swift 5

I am using Xcode 11.2.1, Swift 5, and have a view that is presented Modally. Via storyboard I added a navigation bar and have two navigation items, left, cancel, right, save. I am trying to get the title of the view to display. I have tried via viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "New " + costumeChoice
imageFromFileButton.alpha = 0.5
imageFromFileButton.isEnabled = false
costumeImageView.image = UIImage(named: "PauPlaceholder")
}
I have tried "self.navigationItem.title = "New " + costumeChoice" through viewWillAppear and through viewDidAppear, but no luck.
What am I missing?,
You have to present the NavigationController which embedded your ViewController, that way a navigationBar will be presented.
For example:
Assuming that your current ViewController is CurrentViewController
and viewController which you want to present is DestinationViewController
In order to present the destinationController you have to do this: -
// self ==> CurrentViewController
self.present(UINavigationController(rootViewController:DestinationViewController(), animated: true)

Present viewcontroller with tabbar

I created UITabBarController programmatically in AppDelegate with 4 view controllers(using .xib). When user tap some button on ViewController (VC-A) it present another VC (VC-B) and covered tabbar. So I want to VC-B has a tabbar on the button.
I tried to add VC-B as a child of tabbarcontroller. I tried to .present(vc) and .show(vc) on both: VC-A and VC-A.TabBarController
Creating controllers in AppDelegate:
let controllers = [tabViewController1,tabViewController2,tabViewController3,tabViewController4]
tabBarController.viewControllers = controllers
window?.rootViewController = tabBarController
presenting in VC-A
self.tabBarController?.present(controller, animated: false, completion: nil)
right click and drag from tabbar controller in storyboard to VC-B. that should create a tab on the bottom of your VC-A and VC-B to go back and forth without having to implement any backend code unless you want to animate
The solution is to embed every VC in navigationController and then add to TabBarController.
let vc1 = ViewController1()
let navController1 = UINavigationController(rootViewController: vc1)
navController.isNavigationBarHidden = true
let controllers = [navController1, navController2, navController3, navController4]
tabBarController.viewControllers = controllers
window?.rootViewController = tabBarController
Then call
self.navigationController?.pushViewController(controller, animated:
true)
To diplay VC with tabbar
I will press the red login button at the bottom of the picture and try to log in.
login button => "로그인"
After that, log in.
let moreVC = self.storyboard?.instantiateViewController(withIdentifier: "MoreViewController") as! MoreViewController
moreVC.definesPresentationContext = true
moreVC.modalPresentationStyle = .fullScreen
let navController = UINavigationController(rootViewController: moreVC)
self.present(navController, animated: true, completion: nil)
If the login proceeds without error, the above code will be called to display the screen when the login is completed.
If the flow proceeds as the code above, this screen appears.
The screen shown is not fullscreen, and the tabbar at the bottom is gone. The screen I want is the screen below.
How can I present a tab bar when presenting the screen?

Swift - Overwrite navigation bar

When it comes to opening a new View Controller i didnt want it to be presented modally so i pushed it in navigation controller:
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("newView")
self.navigationController!.pushViewController(vc, animated: true)
The View with the identifier "newView" is presented correctly and there is also a navigation bar with a back-button provided, which also works properly.
But how to customize this existing navigation bar, add new bar button items etc.. ?
any suggestions?
Thanks and Greetings!
You are on the right track by subclassing from UIViewController the newView. I doubt you could customize the navigation bar on the storyboard.
You have to do it in code.
In viewDidLoad() of newView, you can have these:
var helloButton = UIBarButtonItem(title: "Hello", style: .Plain, target: self, action: "sayHello:")
self.navigationItem.rightBarButtonItem = helloButton
Implement the sayHello method:
func sayHello(sender: UIBarButtonItem) {
}

hide tab bar in view with push

I have a tabBar + NavigationViewController. The Tab bar has collection view with cells(Say view1) and with cells a push seague is implemented to another view(Say view2).
In view2 I want to have a navBar but no tab bar.
I tried
self.tabBarController?.tabBar.hidden = true,
it worked fine for view2 but when I went back to view1 by back button the tab was still hidden( even after in view1 class I added self.tabBarController?.tabBar.hidden = false in viewDidLoad func).
How can i make the tab bar reappear in view1?
I'm working in swift.
Make sure to check this option only on the ViewController whose tab
bar you wish to be hidden.
Thanks to iHarshil for the suggestion.
In the viewDidload set the UIViewController hidesBottomBarWhenPushed to yes:
self.hidesBottomBarWhenPushed = YES;
This way the UINavigationController takes care of hiding the tab bar.
Use in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
// Hide bottom tab bar in the detail view
destViewController.hidesBottomBarWhenPushed = YES;
}
}
Bruno Fernandes's answer in Swift:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "YourSegueIdentifier" {
let destinationController = segue.destinationViewController as! YourViewController
destinationController.hidesBottomBarWhenPushed = true
}
}
This was the answer that worked for me. Putting hidesBottomBarWhenPushed in the viewDidLoad method didn't work.
Thanks Bruno!
In my case, I use hidesBottomBarWhenPushed before I push the destination view controller.
func showSecondViewController() {
let vc = SecondViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
You have to work with viewWillAppear or viewDidAppear. viewDidLoad will be called when view1 is loading (showing) the first time. If you move from view1 to view2 and back the viewDidLoad won't be called again. Therefore you have to use viewWillAppear or viewDidAppear like
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.hidden = false
}
Put this code in your view1 controller. The viewWillAppear or viewDidAppear will be called every time navigating back to view1
if you want to hide TabBarController Bottom Bar : #Swift 3
In YourViewController : in ViewDidLoad() method
self.tabBarController?.tabBar.isHidden = false

PresentModalViewController not showing navigation bar on next view

Hello I am using One tab bar button on toolbar , this button will show next view with table view ,Here is my code
[self presentModalViewController:self.navigationController
animated:YES];
my problem is that when I click this tab bar button it will showing next view with tableview but not navigation bar. because of this i am unable to perform delete operation in tableView.
How to solve the issue?
If you dont find the UINavigationBar on the next class means , it does not have a navigation controller, so before pushing it add a UINavigationController to your next view.
Try like this:
NextViewController *nextViewController=[[NextViewController alloc]initWithNibName:#"NextViewController" bundle:nil];
UINavigationController *navBar=[[UINavigationController alloc]initWithRootViewController:nextViewController];
[self.navigationController presentModalViewController:navBar animated:YES];
[navBar release];
[nextViewController release];
see this stackoverflow question for edit option.
You can simply add a button to navigation bar with ease
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(editTable)] autorelease];
-(void)editTable{
[tableView setEditing: YES animated: YES];
}
All the best.
This code is called on button click event in classA VC:
ClassBVC* bVc = [[ClassBVC alloc] initWithNibName:#"ClassBVC" bundle:nil];
UINavigationController* tempNavCon = [[UINavigationController alloc] initWithRootViewController:bVc];
[self presentModalViewController:tempNavCon animated:YES];
[tempNavCon release];
[bVc release];
bVc = nil
;
and in class BVC in view did load you make an UIbarbutton item e.g:
UIBarButtonItem* barButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonClicked:)];
[barButton setTitle:#"Back"];
[self.navigationItem setLeftBarButtonItem:barButton];
[barButton release];
And in buttonClickedMethod simply dismiss the the model controller as:
-(void)backButtonClicked:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
That is because you are using Modal to bring the new view controller.
Modally added/presented view controller will not be added to the navigation controller stack
if you are using navigationcontroller use like this
[self.navigationController pushViewController:nextController animated:YES];
Add navigation bar as sub view to the new view with bar button.
Try this
-(IBAction) editClick:(id)sender
{
[tableView setEditing:![tableView isEditing] animated:YES];
}
Swift 5
import UIKit
class ListVC: UIViewController {
// MARK: - Init
override func viewDidLoad() {
super.viewDidLoad()
//Background of the first screen
view.backgroundColor = .yellow
//Calling the instance of the navigation controller
let nav = self.navigationController?.navigationBar
//Defining the black theme on the navigation controller
nav?.barStyle = UIBarStyle.black
//Defining the white characters to make contrast with the black theme on the navigation controller
nav?.tintColor = UIColor.white
//Defining the custom color of the title font from navigation controller
nav?.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.orange]
//Defining the title of the navigation controller
nav?.topItem?.title = "List"
navigationItem.rightBarButtonItem = UIBarButtonItem.init(image: #imageLiteral(resourceName: "AddBtn"), style: .plain, target: self, action: #selector(hello))
// print(Realm.Configuration.defaultConfiguration.fileURL)
let realm = try! Realm()
print(Realm.Configuration.defaultConfiguration.fileURL)
}
// MARK: - Selector
/// A selector function that is called when the 'add' button is pressed on the navigation controller
#objc func hello() {
//Instance of the second screen
let addVC = AddVC()
//Add the navigationController to the new viewController
let navController = UINavigationController(rootViewController: addVC)
//Presenting the second screen modally
navigationController?.present(navController, animated: true, completion: nil)
}
}
//Other class
import UIKit
class AddVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Background of the view
view.backgroundColor = .white
//Calling the instance of the navigation controller
let nav = self.navigationController?.navigationBar
//Initialize the title for the ViewController
nav?.topItem?.title = "Andrey"
// Initialize the right bar button item
navigationItem.rightBarButtonItem = setUpSaveButton()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
/// Function that returns the "Save" bar button item
private func setUpSaveButton() -> UIBarButtonItem {
let button = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(saveAction))
button.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.systemBlue],
for: .normal)
return button
}
#objc func saveAction() {
print("Saving..")
}
}
Swift 5.1
Presenting ViewController with navigation bar AND toolbar in fullscreen mode. If you don't put the row marked on comment the toolbar never show itself.
let sb = UIStoryboard(name: "retail_mainScreen", bundle: nil)
guard let mainVC = sb.instantiateViewController(withIdentifier: "mainScreen") as? retail_mainGest else { return }
let navController = UINavigationController(rootViewController: mainVC)
navController.isToolbarHidden = false //<--- remember this or toolbar will not appear
navController.modalPresentationStyle = .fullScreen
sender.vista.present(navController, animated: true, completion: nil)