Failing to instantiate initial view controller programmatically - ios

I am running an XCTest where I am trying to instantiate a UINavigationController as the initialViewController but it is giving me the following error:
Could not cast value of type 'ToDo.ItemListViewController'
(0x10cce7208) to 'UINavigationController' (0x10f93ced8)
The ItemListViewController is embedded within the Navigation Controller, and "Is Initial View Controller" is selected for the Navigation Controller. This is exactly how I'm instructed to do this by a tutorial... perhaps I have another setting interfering? Here is my code
func test_InitialViewController_IsItemListViewController() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController =
storyboard.instantiateInitialViewController() as! UINavigationController
let rootViewController = navigationController.viewControllers[0]
XCTAssertTrue(rootViewController is ItemListViewController)
}
Screenshot for reference:

Related

How to access to all possible view controllers in a tabBarViewController from storyboard?

I would like to programmatically construct a replica of the storyboard tabBarController, as follows:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "tabBarViewController")
viewControllers = tabBarController.childViewControllers
My storyboard tabBarController contains 7 tabs. But the code above only provide me with the 4 firsts (on iPhone). How can I get the others tabs from the storyboard?
The problem is because you are using wrong property to get viewcontrollers. You should use viewControllers instead of childViewControllers. Try the code below, it will return 7 controllers for viewControllers value
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "tabBarViewController") as! UITabBarController
let viewControllers = tabBarController.viewControllers;

Opening a View Controller that is connected to a navigation Controller programatically

I am using AKSwiftSlideMenu as basis for an app.
I have a view controller (HomeVC) that is connected to a navigation controller.
If the storyboard entry point is pointing to HomeVC then I get the menu of course, but my app needs to start without the menu and only after certain screens and tasks that are done i want to navigate to HomeVC and allow user access to the menu.
I noticed that if a i place a button on a starting view controller that does not have a connection to the navigation controller, and connect that button directly to the Navigation controller by drag+cntrl then pressing the button will get me from a view controller without a menu to HomeVC and show the menu.
How do i do that programmatically
Thanks in advance for any help
edit: I have tried the following code
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "Home") as! UINavigationController
self.present(newViewController, animated: true, completion: nil)
which did not work resulting with the following err
Could not cast value of type 'myApp.HomeVC' (0x10a159280) to 'UINavigationController' (0x10cc2d3c8).
let newViewController = storyBoard.instantiateViewController(withIdentifier: "Home") as! UINavigationController
s
"Home" is not a UINavigationController. Remove as! UINavigationController from this line and the error will go away.
thank you Daniel for telling me to instantiate navigation controller. Ended up giving navigation controller a storyboard id named ccontroller and the following code does what I needed
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ccontroller") as! UINavigationController
self.present(vc, animated: true, completion: nil)

Notification action open view without Navigation Controller

I'm doing an app which opens a detail view from a push notification.
In my AppDelegate I'm opening the view, but the view doesn't have a navigation controller.
Then I think that my solution is use the method instantiateViewControllerWithIdentifier
to handle the navigation controller, I'm not sure if this is the solution, but here is the question of the title...
My class SlideNavigationController is Objective-C, and when I use the method
let rootVC = UIStoryboard(name: "Main", bundle: nil).
instantiateViewControllerWithIdentifier("SlideNavigationController") as! SlideNavigationController
I get the error:
warning: could not load any Objective-C class information. This will significantly reduce the quality of type information available.
Any idea? Sorry for my English, edits are welcome! Thanks
The problem with my UIController is solved. Here is my code:
let rootViewController = self.window!.rootViewController as! UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let targerView = mainStoryboard.instantiateViewControllerWithIdentifier("view_place_detail") as! VCPlaceDetailTour
targerView.placeId = aps as String
rootViewController.pushViewController(targerView, animated: false)
You can do with this code.
let rootViewController = self.window!.rootViewController as! UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let targerView = mainStoryboard.instantiateViewControllerWithIdentifier("view Identifier") as! PromotionDetailsVC
rootViewController.pushViewController(targerView, animated: false)
I hope this will help you.
You can programatically create a navigation Controller and set the desired view controller as its rootViewController of the navigation controller and then set navigation controller as windows rootViewController.
eg :
let rootVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SlideNavigationController") as! SlideNavigationController
let window = UIApplication.sharedApplication().keyWindow
window.rootViewController = rootVC
Same is expalined in this link too : set initial viewcontroller in appdelegate - swift
You must need to create a bridging header to use objective c controllers in the swift project.
Follow the link below for information on creating bridging header.
How to find path of Bridging-Header.h - Swift, Xcode
After that you must import the .h files of controllers in the bridging header file.
Now you can easily use your objective c view controller in swift project.

Swift: Navigation Bar disappears after programatically embedding tab bar controller

I have just programatically embedded a tab bar controller into my app, however it seems to have forced my Storyboard embedded Navigation Bars to disappear, I assume this is because I have now set the rootviewController to be my tab bar.
I read the answer to this post as it seemed that the problem was similar, however doing so prompts me with the error Pushing a navigation controller is not supported
Below is my code written in AppDelegate, here I create my tab-view and a navigation controller to push to the root view controller:
// Set up the tab and navigation bar controllers
var currController = window?.rootViewController
let chatSB = UIStoryboard(name: "Chat", bundle: nil)
let mainSB = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = UITabBarController()
var navigationController = UINavigationController(rootViewController: currController!)
let profileVC = mainSB.instantiateViewControllerWithIdentifier("profileVC") as TimelineTableViewController
let chatVC = chatSB.instantiateViewControllerWithIdentifier("chatInboxVC") as ChatInboxViewController
tabBarController.viewControllers = [profileVC, chatVC, navigationController]
window?.rootViewController = tabBarController
How would I go about fixing this issue?
If your desired view controllers are embedded in UINavigationController instances you need to instantiate those rather than the desired view controllers directly. The storyboard will take care of instantiating the embedded view controllers.
So, if your two navigation controller scenes have "profileNavController" and "chatInboxNavController" as their identifiers, your code would be -
// Set up the tab and navigation bar controllers
var currController = window?.rootViewController
let chatSB = UIStoryboard(name: "Chat", bundle: nil)
let mainSB = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = UITabBarController()
var navigationController = UINavigationController(rootViewController: currController!)
let profileNavController = mainSB.instantiateViewControllerWithIdentifier("profileNavController") as UINavigationController
let chatNavController = chatSB.instantiateViewControllerWithIdentifier("chatInboxNavController") as UINavigationController
tabBarController.viewControllers = [profileNavController, chatNavController, navigationController]
window?.rootViewController = tabBarController

Load Tab Bar Controller from AppDelegate

I have been trying to figure this out by myself, but couldn't.
I want to load a Tab Bar controller from my AppDelegate (After a successful Google Sign in to the application).
I read here how to load a ViewController from AppDelegate
Perform Segue from App Delegate swift
Code in the example:
// Access the storyboard and fetch an instance of the view controller
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: MainViewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as! MainViewController;
// Then push that view controller onto the navigation stack
let rootViewController = self.window!.rootViewController as! UINavigationController;
rootViewController.pushViewController(viewController, animated: true);
In this example, my TabBar needs both a name and identifier, from what I understood.
Can someone please explain this to me ? I can't find "identifier" on the Tab Bar Controller , only "Title".
Also, I don't have a navigation controller view in my app.
set storyboard ID here
and embed the firstViewController in IB in navigationController
let rootViewController = self.window!.rootViewController as! UINavigationController;
rootViewController.pushViewController(viewController, animated: true);
iOS 13 Update
From version. iOS 13,
The RootViewController will be initiated in scene function located at
SceneDelegate.swift instead of AppDelegate.swift file. which looks like this.
Example:
// Simple init
let mainSB: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let loggedInTabController = mainSB.instantiateViewController(identifier: "loggedInTabController")
self.window!.rootViewController = loggedInTabController

Resources