Swift - UINavigation Controller becoming nil - ios

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.

Related

Get custom NavigationController class from custom UIViewController

I am trying to implement the side navigation menu (one that we have in Android) in iOS App.So far i tried the following:-
AppDelegate.swift :-
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var bridge: RCTBridge!
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let sb = UIStoryboard(name: "mystoryboard", bundle: Bundle.main)
let rootViewController: UIViewController =
sb.instantiateViewController(withIdentifier:
"NativeLabelSwiftViewController") as UIViewController
let navigationController = UINavigationController(rootViewController:
rootViewController)
window = UIWindow(frame: UIScreen.main.bounds)
window!.rootViewController = navigationController
window!.makeKeyAndVisible()
return true
}
The above is my AppDelegate class since it is a React Native project we have the generated code as well.Here added the following code to instantiate my rootViewClass(NativeLabelSwift) by following code :-
let sb = UIStoryboard(name: "mystoryboard", bundle: Bundle.main)
let rootViewController: UIViewController =
sb.instantiateViewController(withIdentifier:
"NativeLabelSwiftViewController") as UIViewController
NavigationLabelSwiftViewController.swift(Custom View Class) :-
class NativeLabelSwiftViewController: UIViewController{
var bridge: RCTBridge!
override func viewDidLoad() {
super.viewDidLoad()
title = "Production Tracking"
let btn2 = UIButton(type: .custom)
btn2.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn2.addTarget(self,
action:#selector(NativeLabelSwiftViewController.
onBtn2Clicked.(_:)), for: .touchUpInside)
let item2 = UIBarButtonItem(customView: btn2)
self.navigationItem.setLeftBarButton(item2, animated: true)
}
#IBAction func onBtn2Clicked(_ sender: UIBarButtonItem) {
if let navViewController = self.navigationController as?
NavigationController {
// navigation view controller is available
}
else{
// navigation view controller not available
}
}
}
The Navigation Controller has a UIViewController class (NativeLabelSwiftViewController) that has a button in Tab Bar.On Press of the Button i need to access the Navigation Controller method.But i am not able to get the navigation controller using the below code :-
let navViewController = self.navigationController as?
NavigationController; //this is NIL
But
let uiViewController = self.navigationController as?
UINavigationController; //this is not NIL
You are not referring your custom navigation controller in the AppDelegate. You used UINavigationController(rootViewController: rootViewController).
You if you want to use the storyBoard NavigationController, In AppDelegate use -
let nav = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NavigationController") as! NavigationController
window = UIWindow(frame: UIScreen.main.bounds)
window!.rootViewController = nav
window!.makeKeyAndVisible()
return true
Note: Don't forget to put an Identifier for the StoryBoard NavigationController.

Set UITabBarController as rootViewController

I have a UITabBarController and I want to show this screen and not the login screen if the user session is still active.
My UITabBarController has 3 ViewControllers and the problem is that I don't see the TabBar links in the bottom and I'm unable to navigate.
Without the following code everything works fine. I mean after login I can navigate.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
if Auth.auth().currentUser != nil {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = HomeTabBarController()
}
return true
}
I have also tried the following code to set the rootViewController but it's the same problem.
When I try to set one of the other view controllers as root (one of the children), the Tab Bar doesn't show at all
var rootView: MyRootViewController = MyRootViewController()
if let window = self.window{
window.rootViewController = rootView
}
What am I doing wrong here?
I was facing same issue and I came across your post, the problem with your code is that HomeTabBarController() is creating a whole new TabBarController so to fix it try the following approach I used.
if Auth.auth().currentUser != nil {
print("******************************User Present******************************")
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// create view controllers from storyboard
// Interface Builder -> Identitiy Inspector -> Storyboard ID
// Set up the Tab Bar Controller to have two tabs
let tabBarController = storyboard.instantiateViewController(withIdentifier: "HomeTabBarController") as! HomeTabBarController
// Make the Tab Bar Controller the root view controller
window?.rootViewController = tabBarController
window?.makeKeyAndVisible()
}
Edit Make sure to add the Identifier to your TabBarController
// Interface Builder -> Identitiy Inspector -> Storyboard ID
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//// this code changes the initial point of aap///////
window = UIWindow(frame: UIScreen.main.bounds)
let nav = UINavigationController()
let myview = SettingTabbar()
nav.viewControllers = [myview]
window?.rootViewController = nav
window?.makeKeyAndVisible()
return true
}
And Function SettingTabbar is:
func SettingTabbar()->(UITabBarController)
{
//Setting TabBar
let tabbar = UITabBarController()
//Designing Tabbar Item Images
let table = UITabBarItem(title: nil, image:UIImage(named: "002-list") , tag: 0)
let collection = UITabBarItem(title: nil, image: UIImage(named: "001-collect"), tag: 1)
let insert = UITabBarItem(title: nil, image: UIImage(named: "add"), tag: 2)
//Getting TabBar ViewControllers
let TableView = newViewController()
let CollectionView = PersonCollectionViewController()
let InsertRec = nextViewController()
//Setting ViewControllers on TabBar Items
TableView.tabBarItem = table
CollectionView.tabBarItem = collection
InsertRec.tabBarItem = insert
let controllers = [TableView,CollectionView,InsertRec]
tabbar.viewControllers = controllers
tabbar.viewControllers = controllers.map{UINavigationController(rootViewController: $0)}
//Setting Title
tabbar.navigationItem.title = "Person Record"
return tabbar
}
The problem is this line:
window?.rootViewController = HomeTabBarController()
That is the wrong HomeTabBarController. It is a totally new HomeTabBarController with no children. You need to fetch the HomeTabBarController that’s in the storyboard.
I finally found the solution: As #matt suggested I had to fetch the HomeTabBarController that’s in the storyboard.
window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
// controller identifier sets up in storyboard utilities
// panel (on the right), it called Storyboard ID
let viewController = storyboard.instantiateViewController(withIdentifier: "HomeTabBarController") as! HomeTabBarController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
window?.makeKeyAndVisible()
window?.rootViewController = viewController

Change view controller on click UIButton Swift (without storyboard)

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.

Navigation Bar Disappears Change Root ViewController and then reassign

I've made the launch screen the root view while my app makes a request to firebase and then reassign the root view once the request has been completed. Unfortunately when I do this my navigation bar disappears or is covered up by the new root view. When I run the simulator I can see the navigation bar briefly and then it get covered up by my TableViewController. How do I keep this from happening?
Here is my code from the AppDelegate where I make all of this happen:
var window: UIWindow?
let searchManager = SearchManager()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
makeRootViewLaunchScreen()
FirebaseApp.configure()
searchManager.getMosaicTitles { results in
self.searchManager.listOfMosaics = results
self.stopDisplayingLaunchScreen()
}
// Adds border to bottom of the nav bar
UINavigationBar.appearance().shadowImage = UIImage.imageWithColor(color: UIColor(red:0.00, green:0.87, blue:0.39, alpha:1.0))
// Override point for customization after application launch.
return true
}
func makeRootViewLaunchScreen() {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "launchScreen")
UIApplication.shared.keyWindow?.rootViewController = viewController
}
func stopDisplayingLaunchScreen() {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "centralViewController") as? SearchResultsTableViewController
viewController?.searchManager = searchManager
UIApplication.shared.keyWindow?.rootViewController = viewController
UIApplication.shared.keyWindow?.rootViewController?.navigationController?.isNavigationBarHidden = false
}
As you can see I tried to use UIApplication.shared.keyWindow?.rootViewController?.navigationController?.isNavigationBarHidden = false to force the navigation bar to appear but it doesn't. My app still looks like this:
You are setting a UIViewController as your Root controller. What you want to do is set a UINavigationController as your Root controller.
Either create a new navigation controller in your storyboard and load that one instead of loading "centralViewController", or modify your function like this:
func stopDisplayingLaunchScreen() {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let viewController = mainStoryboard.instantiateViewController(withIdentifier: "centralViewController") as? SearchResultsTableViewController {
viewController.searchManager = searchManager
// create a new UINavigationController
let newNavVC = UINavigationController()
// set the "root" VC of the NavVC to your SearchResultsTableViewController
newNavVC.setViewControllers([viewController], animated: false)
// use the new NavVC as the new rootViewController
UIApplication.shared.keyWindow?.rootViewController = newNavVC
UIApplication.shared.keyWindow?.rootViewController?.navigationController?.isNavigationBarHidden = false
}
}
Note: not tested, but this should get you on your way.
Edit: Another approach...
Instead of swapping the root controller of the key window, create a ViewController that indicates you are initializing / retrieving your data. That VC can be the "root" of a Navigation Controller.
Put your searchManager.getMosaicTitles function in that VC. When it has finished, replace the current "launch" controller in your Nav Controller with your TableVC. It will look something like this:
// note: searchManager will have to be a reference back to AppDelegate.searchManager
searchManager.getMosaicTitles { results in
self.searchManager.listOfMosaics = results
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let viewController = mainStoryboard.instantiateViewController(withIdentifier: "centralViewController") as? SearchResultsTableViewController {
viewController.searchManager = searchManager
// replace the current Nav VC stack with the new SearchResultsTableViewController
self.navigationController.setViewControllers([viewController], animated: false)
}
}
To prevent the lag between when the navigation bar controller appears and the tableView appears check out the following. Prevent navigation bar from disappearing without lag

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.

Resources