Change view controller on click UIButton Swift (without storyboard) - ios

How do you change the view controller when a button is clicked. I am not using the Storyboard. The views were all created programmatically.
I tried adding a target to the button and then calling the following method to push the new View Controller:
func switchView() {
print(123)
let prodListController = ProductListController()
self.navigationController?.pushViewController(prodListController, animated: true)
}
This was called from within the UIviewController class.
Any help will be greatly appreciated. Thanks!!
EDIT:
Made the following modifications:
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = UINavigationController(rootViewController: ProductListController())

Are you using navigationController? It looks like it is "nil"...
You can do it with "show" instead:
self.show(ProductListController(), sender: self)
However, if you want to use navigationController, you have to set it up first.
For example (supposing you will start your app with a navigationController):
on didFinishLaunchingWithOptions (AppDelegate.swift):
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.main.bounds)
let initialViewController = NavViewController()
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
on viewDidLoad of NavViewController.swift:
self.pushViewController(ViewController(), animated: true)
and then, you can use your code for the button:
func switchView() {
print(123)
let prodListController = ProductListController()
self.navigationController?.pushViewController(prodListController, animated: true)
}

You can try this code to push another viewcontroller
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
var navVC = UINavigationController()
var yourVC = YourViewController()
navVC.viewControllers = [yourVC]
self.window!.rootViewController = navVC
self.window?.makeKeyAndVisible()
hope this will resolve your problem.

Related

Programmatically Pushing a ViewController

I'm trying to push a ViewController programmatically.
Code:
var plus = UIButton()
plus.addTarget(self, action: #selector(plusPressed), for: .touchUpInside)
#objc func plusPressed() {
print("plus")
let createJournalVC = CreateJournalViewController()
self.navigationController?.pushViewController(createJournalVC, animated: true)
}
What works:
Once the button is pressed, "plus" is printed to the console.
What doesn't work:
The ViewController is not pushed.
Details
I am using a Navigation Controller & Tab Bar Controller.
I am making this only programmatic, no storyboards.
There is no error printed to the console, nothing actually happens.
If TabBarController comes after NavigationController then NavigationController can become nil. You should rather put TabBarController first and then put each ViewController (that are related to each tab) into there own NavigationController.
Storyboard:
Programmatically:
You need to create your TabBarController like this...
window = UIWindow(frame: UIScreen.main.bounds)
let tabCon = UITabBarController()
let navCon1 = UINavigationController(rootViewController: ViewController())
let navCon2 = UINavigationController(rootViewController: CreateJournalViewController())
let navCon3 = UINavigationController(rootViewController: AnotherViewController())
tabCon.viewControllers = [navCon1, navCon2, navCon3]
tabCon.tabBar.items?[0].title = NSLocalizedString("VC", comment: "comment")
tabCon.tabBar.items?[1].title = NSLocalizedString("CJV", comment: "comment")
tabCon.tabBar.items?[2].title = NSLocalizedString("AVC", comment: "comment")
window?.rootViewController = tabCon
window?.makeKeyAndVisible()
It seems navigationController is nil, that's why the view controller is not pushed.

How can I embed my navigation controller into my tab bar controller programmatically in Swift Xcode 8.2?

I have been teaching my self how to develop and I got to the point to where I need guidance from experts. I created some of the user interface programmatically using the MVC structure. My question is how can I embed my navigation controller into my tab bar controller so my tab bar controller can be on every screen. I made the tab bar controller in main.storyboard and referenced it in the View controller I named Home Controller.
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabViewController = storyboard.instantiateViewController(withIdentifier: "TabBar")
self.present(tabViewController, animated: true, completion: nil)
The code above is in the view did load function. I was wondering do I need to change up the root view controller in my app delegates?
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))
This is in my finished launched func.
Use following lines
var navigationController = UINavigationController(rootViewController: viewController));
tabBarController.viewControllers = [navigationController,firstViewControllersecondViewController, ]
create a separate UITabBarController class and initialize it in AppDelegate like this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = MyTabBarController()
window?.makeKeyAndVisible()
return true
}
and the custom tabBarController
import UIKit
class MyTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.barTintColor = UIColor.black
self.tabBar.tintColor = UIColor.white
self.tabBar.unselectedItemTintColor = UIColor.white.withAlphaComponent(0.4)
let firstViewController = FirstViewController()
let firstViewTabBarItem = UITabBarItem(title: "First", image: UIImage(named: "calculator"), selectedImage: UIImage(named: "calculator"))
firstViewController.tabBarItem = firstViewTabBarItem
firstViewController.tabBarItem.tag = 0
let historyViewController = HistoricDataViewController()
historyViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .history, tag: 1)
let tabBarList = [calculateViewController, historyViewController]
viewControllers = tabBarList.map{UINavigationController(rootViewController: $0)}
}
}
Hope this example helps.

Error trying to programmatically add a controller file to a navigation controller without creating storyboard

I am trying to push a view controller onto a navigation controller without designing a storyboard. Is this possible as I am new to Swift? I created my navigation controller in appdelegate.swift file:
let viewController: UIViewController = ViewController(nibName: nil, bundle: nil)
viewController.view.backgroundColor = UIColor.white
let navController: UINavigationController = UINavigationController(rootViewController: viewController)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.backgroundColor = UIColor.darkGray
self.window?.rootViewController = navController
self.window!.makeKeyAndVisible()
And now in ViewController.swift file, when the user clicks the button below is the file when I try to add the signInController:
func SignIn(sender: UIButton!) {
print("Im, here")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "signInController") as! signInController
self.navigationController?.pushViewController(controller, animated: true)
}
Below is my Error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard (<UIStoryboard: 0x608000269600>) doesn't contain a view controller with identifier 'signInController''
Question:
Do I have to create a storyboard and go to the inspector Id to add the storyboard Id? But what if I wanted to accomplish this without creating a storyboard file?
If you are not using a storyboard then you shouldn't attempt to create your sign-in view controller from a storyboard. Change the code to create the view controller directly:
func SignIn(sender: UIButton!) {
print("I'm, here")
let controller = signInController()
self.navigationController?.pushViewController(controller, animated: true)
}
BTW - you need to rename everything to follow standard naming conventions. Classnames should start with uppercase letters. All method, variable, and parameters names should start with lowercase letters.
Well you want to create a viewController without using the storyboard and you're still trying to use the storyboard in your code.
Try something like this instead:
var window: UIWindow?
var navigationController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.main.bounds)
// Override point for customization after application launch.
self.window!.backgroundColor = UIColor.white
self.window!.makeKeyAndVisible()
let myViewController: YourNewViewController = YourNewViewController()
self.navigationController = UINavigationController(rootViewController: myViewController!)
self.window!.rootViewController = self.navigationController
return true
}

Swift - UINavigation Controller becoming nil

I have a problem with my UINavigationController when I try to push another controller.
AppDelegate
let testViewController:ProximityQuestionsIntroductionViewController = ProximityQuestionsIntroductionViewController();
self.navController = UINavigationController(rootViewController: testViewController);
self.window = UIWindow(frame: UIScreen.mainScreen().bounds);
self.window!.rootViewController = navController;
self.window!.backgroundColor = UIColor.whiteColor();
self.window!.makeKeyAndVisible();
return true
ProximityQuestionsIntroductionViewController
class ProximityQuestionsIntroductionViewController:UIViewController {
// Controls
var proximityIntroductionView:ProximityQuestionsIntroductionView!;
// Load components when the view is loaded
override func viewDidLoad() {
super.viewDidLoad();
print("nav in viewDidLoad : \(self.navigationController)");
//Hide Nav bar
self.navigationController?.navigationBarHidden = true;
// Set view
self.proximityIntroductionView = ProximityQuestionsIntroductionView(frame: self.view.frame);
self.view = self.proximityIntroductionView;
}
func start(){
print(self);
print("start in controller");
let nextController = ProximityQuestionsProgressViewController();
print("nav in start : \(self.navigationController)");
self.navigationController?.pushViewController(nextController, animated: true);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
I call start from my ProximityQuestionsIntroductionView when a button is clicked.
In the log I see "nav in start : nil" and the controller doesn't change.
For more info :
self is really the ProximityQuestionsIntroductionViewController.
the navigation bar is really hidden
So the navigation controller is ok in viewDidLoad but not in the other function.
Can someone tell me why ?
Thanks!
EDIT : AppDelegate
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("ProximityIntroduction");
self.navController = storyboard.instantiateViewControllerWithIdentifier("NavigationController") as! UINavigationController;
self.navController?.setViewControllers([initialViewController], animated: false)
self.window?.rootViewController = navController;
self.window?.makeKeyAndVisible();
I add navigation Controller to the story Board and change the ID. But I still have a nil value for the UINavigationControllerin the function start
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("ProximityQuestionsIntroductionViewController")
navigationController = UINavigationController.init(rootViewController:initialViewController )
navigationController?.setViewControllers([initialViewController], animated: false)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
Put Story board id for this ProximityQuestionsIntroductionViewController
You must mark the window and navController variables as optional:
var window : UIWindow?
var navController : UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
let testViewController:ProximityQuestionsIntroductionViewController = ProximityQuestionsIntroductionViewController();
self.navController = UINavigationController(rootViewController: testViewController);
if let window = window {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds);
self.window!.rootViewController = navController;
self.window!.backgroundColor = UIColor.whiteColor();
self.window!.makeKeyAndVisible();
}
return true
}
If you created the project from an Xcode template:
Remove the key-value pair for key "Main storyboard file base name" from Info.plist.
Delete the storyboard file Main.storyboard.
The problem came from the view.
Doing this :
// Set view
self.proximityIntroductionView = ProximityQuestionsIntroductionView(frame: self.view.frame);
self.view = self.proximityIntroductionView;
causes the problem. I don't know exactly why but putting all the UIView in the controller directly solved the problem.

Navigating between two viewController

I have set my initial ViewController as rootViewController in appDelegate because I don't use storyboard. It looks like this way:
var window: UIWindow?
var mainNavigationController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.mainNavigationController = UINavigationController()
var mainController: UIViewController? = TineLineViewController()
self.mainNavigationController!.pushViewController(mainController!, animated: true)
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window!.rootViewController = mainController
self.window!.makeKeyAndVisible()
...
...
My application running and my TineLineViewController shows up.
I have in this class a UIButton which call this method:
func postLeft(_sender: AnyObject?)
{
println("go to secound view..")
let secondViewController = PostCreateController()
let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
self.navigationController?.presentViewController(secondViewController, animated: true, completion: nil)
appDelegate.window?.rootViewController = secondViewController
}
This way if I push the button the screen change and my secondViewController shows up, without animation...
If I try to change the view this way:
self.navigationController?.pushViewController(secondViewController, animated: true)
It's still don't have any animations and after the secoundViewController shows up my application crash with this message:
* Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'adding a root view controller as a child of view controller:'
* First throw call stack:
(
I don't know if is it a best way to set my rootviewController class in appDelagate and why can't navigate without adding this line to my potLeft function:
appDelegate.window?.rootViewController = secondViewController
Without this line I can see in my app consol, the secondViewController viewDidLoad method is called, but the controller not shows up, and I get this message to the cosole:
Warning: Attempt to present on whose view is not in the window hierarchy!
How to navigate between two view without use storyboard?
1) Set mainNavigationController to rootViewController
2) Use self.navigationController?.pushViewController(secondViewController, animated: true)
Explanation
Logically your root view controller is UINavigationController while you are setting TineLineViewController to app's delegate rootViewController property. That is why you're getting exception.
self.mainNavigationController = UINavigationController()
var mainController: UIViewController? = TineLineViewController()
self.mainNavigationController!.pushViewController(mainController!, animated: true)
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
// ERROR is here
// self.window!.rootViewController = mainController
// your root view controller should be navigation controller
self.window!.rootViewController = mainNavigationController
self.window!.makeKeyAndVisible()
You can set the secondViewController as rootViewController of the navigationController with animation:
func postLeft(_sender: AnyObject?)
{
println("go to secound view..")
let secondViewController = PostCreateController()
self.navigationController?.setViewControllers([secondViewController], animated: true)
}
Hope this have helped you !

Resources