programmatic navigation back button not showing - ios

here is my code at the appdelegate:
func showMainView()
{
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyBoard.instantiateViewController(withIdentifier: "PRODUCT_TABBAR_VC_ID")
let nav = UINavigationController()
nav.pushViewController(secondViewController, animated: true)
self.window!.rootViewController = nav
self.window!.makeKeyAndVisible()
}
simulator output:
basicaly i want when user press back button then came back main page . i mean initial page .
i am trying with this one but it not working at least one answer for me Navigate Back to previous view controller
Note : #matt said it is imposible. so could you tell me please what should i do . i am new to iOS
Update:
when user select Man that time tabviewcontroller two page only showing list of product about Man. so if user want to see Woman then user back to main page to select Woman then he will see Woman tabviewcontroller two page.

The back button is for returning to an earlier view controller pushed onto a UINavigationController. In your code, there is no back button because there is nothing to come back to; secondViewController is the only view controller pushed onto the UINavigationController.

You should create your hierarchy like so:
----> UIViewController
----> UINavigationController ----> UIViewController ----> UITabBarController
----> UIViewController
EDIT: It will look like that:
This way it will be possible to pop UIViewControllers contained in UITabBarController.

Place following lines within didFinishLaunchingWithOptions in AppDelegate.swift
self.window = UIWindow(frame: UIScreen.main.bounds)
let nav = UINavigationController(rootViewController: FirstViewController())
self.window!.rootViewController = nav
self.window!.makeKeyAndVisible()
Create FirstViewController.swift with following:
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button1 = UIButton(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
button1.setTitle("Man", for: .normal)
button1.tag = 1
self.view.addSubview(button1)
button1.addTarget(self, action: #selector(showAction(sender:)), for: .touchUpInside)
let button2 = UIButton(frame: CGRect(x: 0, y: 250, width: 200, height: 200))
button2.setTitle("Woman", for: .normal)
button2.tag = 2
self.view.addSubview(button2)
button2.addTarget(self, action: #selector(showAction(sender:)), for: .touchUpInside)
}
func showAction(sender: UIButton) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyBoard.instantiateViewController(withIdentifier: "PRODUCT_TABBAR_VC_ID")
if (sender.tag == 1) {
// SHOW MAN
} else if (sender.tag == 2) {
// SHOW WOMAN
}
self.navigationController?.pushViewController(secondViewController, animated: true)
}
}

Related

Navigation Bar removed

I have used navigation item in my app. In the log out method I have popped to root view controller i.e. my loginViewController but while doing so the navigation bar gets removed. I have tried putting the code to load in viewWillAppear but it is still not working. Could you please help me?
Here is my code for log out:
#IBAction func btnLogOutClicked(_ sender: Any) {
let log : LoginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
let window:UIWindow = UIApplication.shared.keyWindow!
let navControl : UINavigationController = window.rootViewController as! UINavigationController
if (!(navControl .isEqual(log)))
{
window.rootViewController = log
}
navControl.popToRootViewController(animated: true)
}
My viewWillAppear-
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.isNavigationBarHidden = false
self.navigationItem.hidesBackButton = true
self.navigationItem.title = "Select Client"
// create a new butto
let button: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
button.setImage(UIImage(named: "logo-icon"), for: UIControlState.normal)
//set frame
button.frame = CGRect(x: 0, y: 0, width: 50, height: 30)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.leftBarButtonItem = barButton
}
Here is my storyboard-
I am using pushViewController to reach to tab bar controller from login view controller
Try below code to change the NavigationController stack :
let oldVCs = self.navigationController?.viewControllers
let newVCs = [UIViewController]()
// Add your root VC in new array of VCs
newVCs.append(oldVCs![0])
// Add your new VC just after your root VC
let log : LoginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
newVCs.append(log)
self.navigationController?.setViewControllers(newVCs , animated: true)
In this the animation will be like pushing a new controller in stack.
If you want to completely leave that stack and create a new one:
let log : LoginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
let loginNavigationController = UINavigationController(rootViewController: log)
self.view.window?.rootViewController = loginNavigationController

Custom UINavigationItem class - Title dependent on Active UIStoryboard

I've created an App which has three storyboards. ( & multiple VC's) I am creating a global NavigationItem class, that I can enter in storyboard so every view controller inherits the same information and I only have to code one page rather than copying and pasting into each VC.
I want to set the title programmatically. The title can change depending on which storyboard is active and what size phone is present. i.e full title or shorthand if it is displaying on an iPhone SE.
I can't use. UIStoryboard as a bool, as it doesn't conform. How can I tell which storyboard I'm in, so it can set the title in an if statement? The code i've written is wrong and doesn't work for the storyboard.
My code setup so far for my NavigationItemCustom class is bellow I am finding it difficult to find which storyboard i'm in? Can anyone push me in the right direction, please. My code is as follows:
import UIKit
class NavigationBarSetUp: UINavigationItem {
override func awakeFromNib() {
super.awakeFromNib()
let currentstoryboard = UIStoryboard()
let screenWidth = UIScreen.main.bounds.width
let storyboard1 = UIStoryboard(name: "First", bundle: nil)
//let storyboard2 = UIStoryboard(name: "Second", bundle: nil)
//let storyboard3 = UIStoryboard(name: "Third", bundle: nil)
//Current title
self.title = nil
if currentstoryboard == storyboard1 && (screenWidth == 320) {
self.title = " diet 1"
print ("called short title")
} else if currentstoryboard == storyboard1 && (screenWidth > 320) {
// rest of screen sizes
self.title = " Welcome to diet 1"
print ("called full title")
}
// Repeat if statement for storyboards 2 & 3 with different titles.
// Rest of Class code - Bar Button Item Setup
self.hidesBackButton = false
self.leftItemsSupplementBackButton = true
// Left Side Button Setup
let buttonView = UIToolbar()
buttonView.frame = .init(x: 0, y:-7, width: 30, height: 30)
// Setting UIToolbar Transparency of the toolbar
buttonView.setBackgroundImage(UIImage(),
forToolbarPosition: .any,
barMetrics: .default)
buttonView.setShadowImage(UIImage(), forToolbarPosition: .any)
// This is a UIView the Toolbar will sit inside which will then be placed into the Navigationbar.
let navigationContainer = UIView()
navigationContainer.frame = .init(x: 0, y:0, width: 30, height: 30)
// ButtonBarItems Set Up
let ModalButton = UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(NotesButtonClicked))
let negativeSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: self, action: nil)
negativeSpace.width = -10
//Add ButtonBarItems into the UIToolbar ButtonView
buttonView.setItems([negativeSpace, ModalButton], animated: false)
// Add UItoolbar into UIView
navigationContainer.addSubview(buttonView)
//Icon Size to fit
buttonView.sizeToFit()
//Convert UIView into Barbutton Item to set in the Navigation Bar
let topLeft = UIBarButtonItem()
topLeft.customView = navigationContainer
self.setLeftBarButton(topLeft, animated: false)
// Setup of the Right Handside Menu Button
let BurgerButton = UIButton()
BurgerButton.frame = .init(x: -1, y: 0.5, width: 62, height: 25)
BurgerButton.setBackgroundImage(UIImage(named: "BurgerButton1.pdf"), for: .normal)
BurgerButton.addTarget(self, action: #selector(MenuClicked), for: .touchUpInside)
let topRight = UIBarButtonItem()
topRight.customView = BurgerButton
self.setRightBarButton(topRight, animated: true)
}
// Calls the Left Button Action.
func NotesButtonClicked(_ sender: UIBarButtonItem) {
print("Notes Modal Is Called")
//Code here
}
// Calls the Right Button Action.
func MenuClicked(_ sender: UIButton) {
print("Menu is Opened - Rightside")
//Code here
}
}
Well, you are doing a couple things that won't work:
let currentstoryboard = UIStoryboard()
You just created a NEW instance of a (empty) UIStoryBoard object...
let storyboard1 = UIStoryboard(name: "First", bundle: nil)
You just created a NEW instance of a UIStoryBoard object, referencing the Storyboard named "First" (assuming it exists in your app).
Those two instances could never be equal.
UIViewController has a .storyboard property, which is "The storyboard from which the view controller originated."
However, even if you tried:
let currentstoryboard = self.storyboard
let storyboard1 = UIStoryboard(name: "First", bundle: nil)
if currentstoryboard == storyboard1 { ... }
They will still never be equal, because storyboard1 is a new instance.
You might try:
let sbName = self.storyboard?.value(forKey: "name") as? String
if sbName == "First" { ... }
Unfortunately, that does not seem to be documented by Apple, and may very possibly and up getting your app rejected.
I'd think you would be much better off using your own variables / properties to keep track of what's what.

How to add a navigation controller programmatically in code but not as initial view controller

I am relatively new to swift and iOS and can't find an answer or any help for my problem that works.
I want to create a navigation controller view when I click on a button in my previous view. My previous view is an on-boarding with a button on the last page. I successfully connected the button to my next view but I am not able to make the view act like a navigation controller. For example, when a navigation bar is displayed, I am not able to add navigation items to it.
Is there a way to set the new view I create by clicking my button in the first view to be the root controller for my navigation view?
A short version of my code:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRect(x: view.frame.width / 2, y: view.frame.height / 2, width: 40, height: 40))
button.backgroundColor = .red
button.tintColor = .white
button.setTitle("Test", for: .normal)
button.addTarget(self, action: #selector(change), for: .touchUpInside)
view.addSubview(button)
}
func change () {
let otherView = SecondViewController()
self.present(otherView, animated: true, completion: nil)
}
}
class SecondViewController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .yellow
}
}
The SecondViewController gets displayed with a navigation bar but I had problems implementing navigation items, because they weren't shown.
Does the second view controller I present have to be of type UIViewController or UINavigationController?
I am aware that there are easier ways to achieve my goal with the use of the storyboard but in my opinion I understand it better by making my own references via code instead of creating them by dragging them out of the storyboard.
Edit: I have no Objective-C background and learning Swift for about 4 weeks now.
You can add UINavigationController like below :
First you have to create object of SecondViewController,
let myViewController: SecondViewController? = storyboard?.instantiateViewController(withIdentifier: "SecondViewController")
Or
let myViewController: SecondViewController? = SecondViewController(nibName: "SecondViewController", bundle: nil)
Or
let myViewController: SecondViewController? = SecondViewController()
Then add Navigation to SecondViewController
let myNavigationController = UINavigationController(rootViewController: myViewController!)
If you want to present then use :
self.present(myNavigationController, animated: true) {
}
If you want to push then use :
self.navigationController?.pushViewController(myNavigationController, animated: true)
If you want to set as root controller then use :
let appDelegate: AppDelegate = (UIApplication.shared.delegate as? AppDelegate)!
appDelegate.window?.rootViewController = myNavigationController
var objVC: UIViewController? = storyboard.instantiateViewController(withIdentifier: "ViewController")
var aObjNavi = UINavigationController(rootViewController: objVC)
Now, instead of using view controller object use navigation controller object.

Make a Button show a new View on click, without using a Segue?

I'm working on a multi-page brochure app, and have used segues to join pages. I'm getting to the point where I have 20 or so pages and the segue system seems messy.
I have created a button programmatically in the ViewController. I'm just looking to make that button always links to a different View no matter what page it is on. This would mean I wouldn't have to draw segues hundreds of times!
class ViewController: UIViewController {
override func viewDidLoad() {
let button:UIButton = UIButton(frame: CGRect(x: 25, y: 50, width: 250, height: 75))
button.backgroundColor = .black
button.setTitle("", for: .normal)
button.addTarget(self, action:#selector(self.buttonClicked), for: .touchUpInside)
self.view.addSubview(button)
}
func buttonClicked() {
print("Button Clicked")
}
I can't find any code anywhere that would allow me to do this, so I'm wondering if it's even possible.
Any help is appreciated.
I am assuming that you want to show another page programmatically without segue.Here is the sample code.
let storyboard: UIStoryboard = UIStoryboard(name: "yourStoryboardName", bundle: nil)
let vc: UIViewController = storyboard.instantiateViewControllerWithIdentifier("YoourViewControllerStoryBoardID") as UIViewController
self.present(vc, animated: true, completion: nil)
This method creates a new instance of the specified view controller each time you call it.
If you already have the pointer to viewController just present it.
I think the best way to do something like this is a PageViewController.
it automatically adds swipe gestures and ...
there is complete tutorial about it here:
some demo:
Ok here's what i understand, you want to switch ViewControllers on button press.
For the ViewController you want it to Seque too, Add Signupvc to 'Storyboard ID' below Custom Class on the right hand side.
#IBAction func differentSequeAction(sender: AnyObject)
{
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let SignUp: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "Signupvc")
self.present(SignUp, animated: true, completion: nil)
}

Can't push because self.navigationController is nil

I'm presenting a Navigation Controller as a popover. First time a do it I can push to another View Controller with any issue. But, second time a present another controller the same way I can't perform a push because the self.navigationController of the presented Controller is nil. This is the piece of code I'm using to present the Controller
func instantiateEditController(view : UIView) -> UINavigationController
{
let popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("Edit Controller") as MCMEditController
popoverContent.preferredContentSize = CGSizeMake(320, 480)
let navController = MCMBaseNavigationController(rootViewController: popoverContent)
navController.modalPresentationStyle = UIModalPresentationStyle.Popover
navController.navigationBar.tintColor = UIColor.whiteColor()
let popover = navController.popoverPresentationController
popover?.sourceView = view
popover?.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height)
return navController
}
Note: The Navigation Controller is always presented, but just the first time I perform pushes. And this code is for be used in iPad.
Because of the nature of Storyboards and not being able to show that here, I'm not sure where your issue is exactly.
However I successfully setup a project that works using segues. I changed your code to the following:
func instantiateEditController(view : UIView) -> UINavigationController
{
if let popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("Edit Controller") as? MCMEditController {
popoverContent.preferredContentSize = CGSizeMake(320, 480)
let navController = UINavigationController(rootViewController: popoverContent)
navController.modalPresentationStyle = UIModalPresentationStyle.Popover
navController.navigationBar.tintColor = UIColor.whiteColor()
let popover = navController.popoverPresentationController
popover?.sourceView = view
popover?.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height)
return navController
} else {
return UINavigationController(rootViewController: self) // not recommend to keep this, I'm on Swift 1.2 and this was an easy fix to resolve the errors
}
}
To present this popover I set up this IBAction in my ViewController (sender in my case was a UIButton)
#IBAction func presentPopover(sender: AnyObject) {
if let view = sender as? UIView {
let controller = instantiateEditController(view)
let popover = UIPopoverController(contentViewController: controller)
popover.presentPopoverFromRect(view.frame, inView: self.view, permittedArrowDirections:UIPopoverArrowDirection.Any, animated: true)
}
}
The last thing that could be the issue is make sure your segues are using the segue type "show" for all the segues to make sure the transition between them use the navigation controller push:
Hope this helps!

Resources