Swift: Can't Add Button to Navigation Bar of ABPersonViewController - ios

I've noticed that if I have a UIViewController in a UINavigationController, something like:
let vc = UIViewController()
let nav = UINavigationController()
nav.viewControllers = [vc]
self.presentViewController(nav, animated: true, completion: nil)
Adding a button the navigation bar is as easy as: vc.navigationItem.leftBarButtonItem = ...
If however, the view controller is of type ABPersonViewController, like this:
let person = ABPersonViewController()
person.personViewDelegate = self
person.displayedPerson = info
let nav = UINavigationController()
nav.viewControllers = [person]
self.presentViewController(nav, animated: true, completion: nil)
I can't add a button the navigation bar in the same way; person.navigationItem.leftBarButtonItem = ..., as seems to be done here, does nothing.
Is there, then, a way to add a button to the navigation bar of an ABPersonViewController?

You cannot add a button on ABPersonViewController. Even if you are able to add, it will be rejected by apple. What you can do is make a custom view like ABPersonViewController and change whatever you want in it. (My personal opinion is that ABPersonViewController is fine and you should not have a problem living with it).

Your best bet is to just create a View Controller file for your ABPersonViewController and set the button normally in viewDidLoad.
ie:
self.navigationItem.leftBarButtonItem = menuButton
You could add the button to the bar non-programatically by adding a Navigation Item to the view and then adding a bar button item.

Related

Navigation bar not appearing

Can someone help me with this? :(
The navigation bar is not appearing. This is presented by a rootViewController.
You have not posted any code still guessing.
Just taking UINavigationController in storyboad doesn't means that it will appear by default.
You are just presenting view controller. You need to embed in navigation controller or give storyboard identifier to navigation controller and present that.
Example :
let yourviewController = self.storyboard?.instantiateViewController(withIdentifier: "yourVCIdentifer")
let nav = UINavigationController(rootViewController: yourviewController)
self.present(nav, animated: true, completion: nil)

Swift How to present Tabbar on Button click

In my project i want to present Tabbar on button click, now i have already created tabbar and i give identity name as "tabbar" that i show you in below image
so now i am using below code to call Tab bar controller but i am not getting it.
let tabbar: UITabBarController? = (storyboard.instantiateViewController(withIdentifier: "tabbar") as? UITabBarController)
navigationController?.pushViewController(tabbar, animated: true)
can you guys suggest me what i need to do and which code is useful to me to present Tabbar controller.
For more specification : i added below image in which there is blue button in one viewController i want to present tab bar controller on click of that blue button
Thank you.
Try this and see:
Using Storyboard Segue: Connect your segue as present modally with your action button.
Programatically: Use self of view controller (UIViewController) and present it modally, like this.
if let tabbar = (storyboard.instantiateViewController(withIdentifier: "tabbar") as? UITabBarController) {
self.present(tabbar, animated: true, completion: nil)
}
Here is result:
Use this, you dont have the Navigation controller over there, thats why it won't push that way, instead, you need to use following code:
self.present(tabbar, animated: true, completion: nil)
You should be aware that Apple's HIG (Human Interface Guidelines) say that if you have a tabbed application that should be the root-level navigation for the entire app. you're not supposed to do what you are trying to do from a human interface perspective.
That said, it should be technically possible.
My guess is that you don't have a navigation controller.
Use the debugger to check the value of self.navigationController, or add a print statement:
let tabbar: UITabBarController? = (storyboard.instantiateViewController(withIdentifier: "tabbar") as? UITabBarController)
print("navigationController = \(navigationController)")
print("tabbar = \(tabbar)")
navigationController?.pushViewController(tabbar, animated: true)
If either navigationController or tabbar displays as nil, that's your problem.
Select the viewController from which the button click triggered and Select Editor form xcode menu->Embed In->NavigationController.
then write this in button action
let tabbar: UITabBarController? = (self.storyboard?.instantiateViewController(withIdentifier: "tabbar") as? UITabBarController)
self.navigationController?.pushViewController(tabbar!, animated: true)
According to your images I think that your tabBarController has no back button. Means user cannot go back.
If that is the case you can do this.
let tabBar = self.storyboard?.instantiateViewController(withIdentifier: "tabBar")
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = tabBar

How to have TabBarController at the bottom itself on selecting menu Item from the side menu?

I'm using SWRevealController to have a side menu. In my app ,it also have UITabBarcontroller.
My connection format is as SWRevealViewController--->UItabbarController--->NavigationController--->UITabbaritemPage-->Another vc
PLEASE CLICK ON THE IMAGE TO SEE IN CORRECT ORIENTATION
The above show is the layout I'm using.I want to have that burger button (menu button) in almost all vc that are showing from and in tabbarcontroller. Currently I'm getting the side menu when tapping on the Button (The image showed in right side as spereate).On choosing a menu, it shows the desired vc but,the bottom tab bar is not there. I want to have the bottom tabbar in entire pages also in pages from the side menu.
How can I acheive this? Please help me.
The code I'm using in didSelectRowAtIndexPath is:
if indexPath.row == 1{
let destinationVc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
let newFrontVc = UINavigationController.init(rootViewController:destinationVc!)
revealViewController.pushFrontViewController(newFrontVc, animated: true)
}
I think you don't actually need to push a view controller if using tab bar controller.
let tabBarController = self.storyboard?.instantiateViewController(withIdentifier: "TabBarController")
tabBarController.selectedIndex = 1
revealViewController.pushFrontViewController(tabBarController, animated: true)
You would have to set the identifier of the tab bar controller to be TabBarController in Main.storyboard for this to work.
I also had the same layout like you only few view controllers has been added to the tabbar and it will show the tab bar in all view controllers
SWRevealViewController with TabBarController using XIB in Swift 4
let objSideBarVC = SideBarVC(nibName: "SideBarVC", bundle: nil)
let navSidebar = UINavigationController(rootViewController: objSideBarVC)
navSidebar.navigationBar.isHidden = true
let objDashboardVC = DashboardVC(nibName: "DashboardVC", bundle: nil)
let navDashboard = UINavigationController(rootViewController: objDashboardVC)
navDashboard.navigationBar.isHidden = true
let mainRevealController = SWRevealViewController.init(rearViewController: navSidebar,frontViewController: navDashboard)
AppDelegate().window?.rootViewController = mainRevealController
mainRevealController.pushFrontViewController(TabBarController, animated: true)

Swift SideMenu show view controller

So I'm having a table view controller and using https://github.com/jonkykong/SideMenu i'm trying to display a "slide in" sidebar which works, but it doesn't show me the view that I want in the sidebar is black
// Define the menus
let menuLeftNavigationController = UISideMenuNavigationController()
menuLeftNavigationController.leftSide = true
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration of it here like setting its viewControllers.
SideMenuManager.menuLeftNavigationController = menuLeftNavigationController
// Enable gestures. The left and/or right menus must be set up above for these to work.
// Note that these continue to work on the Navigation Controller independent of the View Controller it displays!
SideMenuManager.menuAddPanGestureToPresent(toView: self.navigationController!.navigationBar)
SideMenuManager.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
When It clicks on the sidebar button I have this, which creates the animation but doesn't show the viewcontroller
func someAction(){
present(SideMenuManager.menuLeftNavigationController!, animated: true, completion: nil)
debugPrint("clicked")
}
On the repo readme, you will find your answer, take a look on the Customization
section https://github.com/jonkykong/SideMenu#sidemenumanager.
Simply set menuFadeStatusbar = false
SideMenuManager.default.menuFadeStatusBar = false
From the previous link, you will find the following information : "Draws the menuAnimationBackgroundColor behind the status bar. Default is true.
If menuFadeStatusBar is true, this color is used to fade it. Default is black."
The answer is in the comment of the snippet you posted:
// UISideMenuNavigationController is a subclass of UINavigationController,
// so do any additional configuration of it here like setting its viewControllers.
let btnMenu:UIButton = UIButton()
btnMenu.frame = CGRect(x: 20*valuePro, y: 20*valuePro, width: 40*valuePro, height: 40*valuePro)
btnMenu.backgroundColor = .red
btnMenu.addTarget(self, action: #selector(self.displayMenu), for: .touchUpInside)
self.view.addSubview(btnMenu)
#objc func displayMenu(sender: UIButton!) {
print("Button Clicked")
present(SideMenuManager.default.menuLeftNavigationController!, animated: true, completion: nil)
}
https://github.com/jonkykong/SideMenu
The SideMenu README
Code Implementation
First:
import SideMenu
From a button, do something like this:
// Define the menu
let menu = UISideMenuNavigationController(rootViewController: YourViewController)
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration
// of it here like setting its viewControllers. If you're using storyboards, you'll want to do something like:
// let menu = storyboard!.instantiateViewController(withIdentifier: "RightMenu") as! UISideMenuNavigationController
present(menu, animated: true, completion: nil)
Answer
You need use UISideMenuNavigationController(rootViewController:), not UISideMenuNavigationController().
If you open the side menu from left, set leftSide to true.
let menu = UISideMenuNavigationController(rootViewController: YourViewController)
menu.leftSide = true
present(menu, animated: true, completion: nil)
Of course, you should give instance variable to UISideMenuNavigationController(rootViewController:).
I can recommend using JASidePanels
It's pretty simple and it just works. You're creating an JASidePanelController, setting this class to empty viewcontroller in your Storyboard and making this controller initial. (do not forget to import JASidePanels at the top of the class)
Then, in this class, you're implementing awakeFromNib() method like this:
leftPanel = ..//instantiating menu controller
let centerController = ...//instantiating center controller
centerPanel = UINavigationController(rootViewController: centerController)
That's it.
You can instantiate controller via their ID which can be set in Identity Inspector
let stb = UIStoryboard(name: "Main", bundle: nil) //instantiating a storyboard we will use for instantiating controllers
let someController = stb.instantiateViewController(withIdentifier: "here_your_identifier_goes") as! YourControllerClass

Navigation Bar Not Showing after Adding NavigationController

I have an existing UITableViewController that I've embedded in a NavigationController. However, the Navigation Bar is not showing when I present the view.
Presenting the TableViewController (its Storyboard id is: SelectServicesController) :
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
This is what it looks like when I build (nav bar does not show):
So I just did this and at fist could not get it to show up at all. Then Figured it out, You just need to select the navigation controller and set it to be the ✅is initial View Controller
This is what your storyboard should look like
Then to make everything show up I added this to my viewDidLoad of the view the Navigation controller is presenting. This step is more optional.
self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
self.navigationController?.navigationBar.tintColor = UIColor.blackColor()
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.blackColor()]
navigationController?.navigationBar.hidden = false
And this is what it looks like
mmmm Red on black 🤓 Hope that helps you.
You're presenting a UITableViewController, which doesn't have a navigation controller as a parent (even though your Storyboard has it first, you're not actually using it).
You can fix this by doing something like this:
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
let navigationController = UINavigationController(rootViewController: selectServicesController)
self.navigationController?.presentViewController(navigationController, animated: true, completion: nil)
}
Or by setting the navigation controller as the initial view controller of the storyboard and then calling it like this:
if let selectServicesController = self.storyboard?.instantiateInitialViewController() {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
I encountered the same problem. I solved it by Changing the segue to the navigation controller that embeds the View Controller I want to display.
Hopefully it would work for you.
Let me know if it is a bad practice.
let storyboard = UIStoryboard(name: "Expense", bundle: Bundle(for: PTCAddExpenseViewController.self))
let controller = storyboard.instantiateViewController(withIdentifier:"AddExpense") as! PTCAddExpenseViewController
let navigationController = UINavigationController(rootViewController: controller)
self.present(navigationController, animated: true, completion: nil)
Adding this works for me:
self.navigationController?.isNavigationBarHidden = false
You're presenting the table view controller directly, not its navigation controller. If you mark the nav controller as the initial view controller (tick the "Is initial view controller" box in the attributes inspector), then you can instantiate and show it by:
if let selectServicesNavController = self.storyboard?.instantiateInitialViewController() as? UINavigationController {
// if you're pushing it onto an existing nav controller
self.navigationController?.presentViewController(selectServicesNavController, animated: true, completion: nil)
// if not (and this is probably the case), set the nav controller as your window's rootViewController
UIApplication.sharedApplication().keyWindow.rootViewController = selectServicesNavController
}
My guess is Xcode is ignoring the fact that your table view controller is embedded in navigation controller when presenting your table view controller with the following code:
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
Instead, I would suggest you modify the Top Bar setting under Simulated Metrics to suit your needs or instantiate your navigation controller instead (the latter is preferred and recommended)
In your code, change this line
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
to this
self.presentViewController(selectServicesController, animated: true, completion: nil)
I read in one of your comments you want to present the table view controller modally, with the navigation bar showing. We can do this using the Storyboard. From the view controller that should display this table view controller modally, Ctrl+Drag from the view controller to the Navigation Controller of the Table View Controller. Then, select Present Modally. Set an Identifier for the segue. Then, in your code for the view controller that is presenting the table view controller modally, call:
self.performSegueWithIdentifier("YourSegueIdentifier", sender: nil)
Another way to do this without having to use any code is if the modal presentation is being triggered by something like a button. Then, you can Ctrl+Drag from that button to the Navigation Controller and select Present Modally.
Or it might be this!!
I had the same problem: the navigation bar was showing on the root view in Storyboard, but when running the Simulator - there was no navigation bar at the top of the views. This solved it:
Navigation Controller > Navigation Bar > UNCHECK Translucent (it is checked by default). This did two things:
My Navigation Bar shows on all subsequent views.
The topmost subview is now at Y=0, and not Y=64.

Resources