Set rootViewController inside a class of UINavigationController - ios

I have a UINavigationController in my storyboard and two viewControllers which perform the following function:
InitialViewController: this would be the application's home screen.
FirstTimeViewController: is the screen that appears when the user open
the app for the first time.
My UINavigationController has a class that have the following code:
- (void)viewDidLoad {
[super viewDidLoad];
if ([[ReadPlist initWithPlist:#"Configuration.plist" key:#"initialConfiguration"] boolValue]){
FirstTimeViewController *firstTimeController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"firstTimeView"]; //or the homeController
[self.navigationController pushViewController:firstTimeController animated:NO];
}else{
InitialViewController *initialController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"initialView"]; //or the homeController
[self.navigationController pushViewController:initialController animated:NO];
}
}
Basically this code verify the .plist file if a particular field is active, if YES means that the application is running for the first time, in this case it calls the corresponding viewController.
But this code is not working and I see a NavigationController with a black view. All I would do is the same thing we do in the interface builder, simply drag a line from the UINavigationController inside a UIViewController and set as "Root View Controller", but in my case I'm trying to do this programmatically.
How I can do this?

When you push to FirstTimeViewController Set Bool (User Default) in controller ViewDidload Or in your Success Code.then after set in your AppDelegate below code.
if(Bool value = Yes)
{
FirstTimeViewController *FS=[[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"FirstTimeViewController"];
UINavigationController *navController=[[UINavigationController alloc]initWithRootViewController:FS];
[navController setNavigationBarHidden:YES];
self.window.rootViewController=navController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
}

My answer is
- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)options
{
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
FirstTimeViewController *firstTimeVC = [navController.storyboard instantiateViewControllerWithIdentifier:#" FirstTimeViewController"];
InitialViewController *initialVC = [navController.storyboard instantiateViewControllerWithIdentifier:#" InitialViewController"];
if ([[ReadPlist initWithPlist:#"Configuration.plist" key:#"initialConfiguration"] boolValue])
{
// FirstTime
navController.viewControllers = [NSArray arrayWithObject:firstTimeVC];
}
else
{
// Initial
navController.viewControllers = [NSArray arrayWithObject:initialVC];
}
[self.window makeKeyAndVisible];
return YES;
}

Related

Skip Login View Controller in the NavigationController

I have a tab bar which contains five tabs. My application does not required user to be logged in. Only some features will be allowed if a user signups or logins.
If a user registered/logged in already, I implemented the following logic in the UserViewController which is connected to the NavigationController. However, in the following logic, user still could able to see that ViewController in one-two seconds.
-(void) viewWillAppear: (BOOL) animated
{
if(isRegistered)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UserProfileViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"UserProfileVewController"];
[self.navigationController pushViewController:vc animated:YES];
}
}
I wonder if a user registered already, how could I skip UserViewController?
I want tabbar clicks to open directly to the UserProfileVewController rather than UserViewController which is login/signup viewcontroller.
In the project's AppDelegate, you could check if user is logged/registered or not, and display the ViewControllers dependently:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
BOOL userIsLoggedIn = AMethodCheckIfUserLoggedIn();
if (userIsLoggedIn) {
UserProfileViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"UserProfileVewController"];
self.window.rootViewController = vc;
}
else{
UserViewController *userViewController = [storyboard instantiateViewControllerWithIdentifier:#"UserViewController"];
self.window.rootViewController = userViewController;
}
//... Other logic goes here
[self.window makeKeyAndVisible];
return YES;
}
You could try having your app delegate (or whomever you want really) conform to the UITabBarControllerDelegate and implement - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController. In there you might be able to do the necessary checks/fiddling of the view controllers maybe.

iOS - Transition between different Storyboard view controllers

I have divided my project into two storyboards:
Main.storyboard - For authenticated user. Also this is the default storyboard.
Login.storyboard - For non-authenticated user.
App delegate file:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if(user is authenticated)
{
[self presentLoginScreen:YES];
return YES;
}
Login Screen in app delegate file:
-(void)presentLoginScreen:(BOOL)animated{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Login" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = vc;
}
On logout, login Screen is presented. I defined this in app delegate file:
-(void)logOut{
//clear data
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Login" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
self.window.rootViewController = vc;
//Show login Screen
[self presentLoginScreen:NO];
}
From viewcontroller of MainStoryBoard(letsay mainstoryboardVc.m), logOut is called as:
-(void)didTouchLogOut{
NSLog(#"GoodBye");
AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate];
[appDelegateTemp logOut];
}
This is causing a lot of issue:
Firstly, when I log out, and move to login screen, I can still see mainstoryboardVc.m in the background which looks very clumsy.
I log out, re-log in and again trying to log out, I see following message:
Presenting view controllers on detached view controllers is discouraged
and login screen is not presented.
I tried many answers on the web on view controller presentations between two storyboards without keeping history, nothing seems to work...
To swap out UIViewControllers there are a few other methods that need to be called when transitioning the root view controller:
Objective-c:
- (void)setRootViewController:(UIViewController *) newRootViewController {
UIViewController* currentViewController = self.window.rootViewController;
if (newRootViewController != currentViewController) {
[currentViewController willMoveToParentViewController:nil];
[currentViewController.view removeFromSuperview];
[currentViewController removeFromParentViewController];
self.window.rootViewController = newRootViewController;
}
}
Swift:
func setRootViewController(newRootViewController: UIViewController) {
if let currentViewController = self.window?.rootViewController {
if currentViewController != newRootViewController {
currentViewController.willMoveToParentViewController(nil)
currentViewController.view.removeFromSuperview()
currentViewController.removeFromParentViewController()
self.window?.rootViewController = currentViewController
}
}
}
Two UIViewController objects are duplicated because you set self.window.rootViewController for both of them. Try that;
Login
-(void)presentLoginScreen:(BOOL)animated{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Login" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
Logout
-(void)logOut{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Login" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
[self presentViewController:vc animated:YES completion:nil];
}

How to push viewcontroller from appdelegate in storyboard inside navigation controller

I am using SWRevealViewController in my project, and I want to open a particular controller when the app receives a notification. I have tried so many solutions but nothing works.
I follow this http://www.appcoda.com/ios-programming-sidebar-navigation-menu/ by using storyboard. My storyboard is designed as below:
When the application receives a notification I want to load Photo view controller within its navigation controller. I tried with the following code in the AppDelegate:
UIStoryboard *st = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
photoViewController *descController = (PhotoViewController*)[st instantiateViewControllerWithIdentifier: #"photoView"];
UINavigationController *frontNavigationController = [[UINavigationController alloc] initWithRootViewController:descController];
SidebarTableViewController *rearViewController = (SidebarTableViewController*)[st instantiateViewControllerWithIdentifier: #"menuController"];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc] init];
mainRevealController.rearViewController = rearViewController;
mainRevealController.frontViewController= frontNavigationController;
self.window.rootViewController =nil;
self.window.rootViewController = mainRevealController;
[self.window makeKeyAndVisible];
This works, but creates a new Navigtion controller, and what I need is to use the one already defined in the storyboard, since it has specific properties.
Any idea?
Thanks
actually SwLRevalViewController Taken the ownership of Root, so do like this
in Appdelegate.m
//initially navigate to your Main controller on SWL
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
NSString *alert = userInfo[#"aps"][#"redirect_url"];
[[NSUserDefaults standardUserDefaults]setObject:alert forKey:#"itemType"];
[[NSUserDefaults standardUserDefaults]synchronize];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
SWRevealViewController *main = (SWRevealViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"SWRevealViewController"];
self.window.rootViewController = main;
}
//it automatically redirect to your root controller
on that main view controller ViewDidLoad check / Navigate to your photo view controller
NSString *getType=[[NSUserDefaults standardUserDefaults]objectForKey:#"itemType"];
if ([gettypeofItem isEqualToString:#"something"])
{
yourPhotoViewController *ivc=[self.storyboard instantiateViewControllerWithIdentifier:#"yourPhotoViewController"];
[self.navigationController pushViewController:ivc animated:YES];
}
else
{
// do nothing
}
You can use following method
NSString *storyBoardName=#"Main_iPad";
if (isPhone)
storyBoardName=#"Main_iPhone";
UIStoryboard *storyBoard=[UIStoryboard storyboardWithName:storyBoardName bundle:nil];
PlayVideoBySocketsScene *controller=[storyBoard instantiateViewControllerWithIdentifier:#"playVideoUsingSockets"];
float disptachTime=2.0;
if (value)
{
disptachTime=1.0;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(disptachTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:controller animated:YES completion:nil];
please try this it may help you. in this when you click on notification this method us called first insted for appdelegate
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
NotificationViewController *notificationViewController = [[NotificationViewController alloc] init];
[navController.visibleViewController.navigationController pushViewController:notificationViewController];
}

How to switch to next controller on button click in ios (programmaticaly)

I am working on single view application. On click of button i want to switch to next page(let say menu controller). Please specify what changes I have to make in appdelegate to add a navigation controller as I am completely new to iOS.
[button addTarget:select action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside]; and implement the selector as
-(void)buttonClick{
UIViewController *menu = [[UIViewController alloc] init];
[self.navigationController pushViewController:menu animated:YES];
}
Add this in the app delegate for the root view controller:
FirstViewController *firstViewController = [[FirstViewController alloc] initWithNibName:#"view name" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController];
self.window.rootViewController = navigationController;
Inside the button click:
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"view name" bundle:nil];
[self.navigationController pushViewController:secondViewController animated:YES];
you have to set UINavigationController as Window.rootViewController like below.
FirstViewController *viewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = navigationController;
You should subclass UIViewController and implement the view however you want. Views can be built programmatically or in interface builder.
Then you would either use segues, storyboard identifiers, or a xib file to load the view.
Might look like this: (assuming you set up the view controllers in a storyboard and connected them with appropriate segues & the identifier below)
-(void)buttonClick{
[self performSegueWithIdentifier:#"MySegueIdentifier"];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString: #"MySegueIdentifier"]) {
MyCustomViewController* vc = (MyCustomViewController*)[segue destinationViewController];
//do something with your view controller, like set a property
}
}
Or maybe like this
-(void) buttonClick {
MyCustomViewController* vc = (MyCustomViewController*)[[UIStoryboard storyboardWithName: #"MyStoryboard"] instantiateViewControllerWithIdentifier: #"MyStoryboardIdentifier"];
[self.navigationController pushViewController: vc animated: YES]; //assuming current view controller is a navigation stack. Or could also do presentViewController:animated:
}
You would add a class subclassing UIViewController to your project, and import it (#import "MyCustomViewController.h" in the .m file of the view controller you're pushing from).
Could also use a xib file, but I won't bother with those since Storyboards are much easier to work with.
Without a storyboard:
Inside the app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
navigationController = [[UINavigationController alloc] init]; //navigation controller is a property on the app delegate
// Override point for customization after application launch.
FirstViewController *firstViewController = [[FirstViewController alloc] init];
[navigationController pushViewController: firstViewController animated:NO];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
Inside your FirstViewController:
-(void) buttonClick {
MyCustomViewController* vc = [[MyCustomViewController alloc] init]; // or maybe you have a custom init method
[self.navigationController pushViewController: vc animated: YES];
}
Very simple:
-(void)ButtonClickActionMethod
{
[button addTarget:select action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
}
Clicked Action:
-(void)buttonClick{
YourViewController *view = [[YourViewController alloc] initWithNibName:#"YourViewController" bundle:nil];
[self.navigationController pushViewController:view animated:YES];
}

How to properly set up UINavigationController and add views to the stack

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
self. window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
UINavigationController *navVC = [UINavigationController new];
UIStoryboard *mStoryboard = [UIStoryboard storyboardWithName:#"your storyboard name" bundle:nil];
ViewController *VC1 = [mStoryboard instantiateViewControllerWithIdentifier:#"VC"];
[navVC setViewControllers:[NSArray arrayWithObject:VC1] animated:NO];
[self. window setRootViewController:navVC];
[self. window makeKeyAndVisible];
return YES;
}
Now this creates a navigationController but when i try to display the secondViewController it does display me the correct Navigation Bar for that view but i see a black background instead of the actual view. Adding secondViewController as a subview works but when i now try to display the third one it does again display me the correct navigation bar with the set title for this view but i still see the secondViewController's view. Now my question how do I add viewController to the navigationController so they are displayed right? do i even have to add them? I've read through the apple class reference but there isn't any code.
try this:
self. window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
UIStoryboard *mStoryboard = [UIStoryboard storyboardWithName:#"your storyboard name" bundle:nil];
ViewController *VC1 = [mStoryboard instantiateViewControllerWithIdentifier:#"VC"];
UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:VC1];
[self. window setRootViewController:navVC];
[self. window makeKeyAndVisible];
return YES;
now inside VC1 push the next view controller to your stack with
// EDIT:
UIStoryboard *mStoryboard = [UIStoryboard storyboardWithName:#"your storyboard name" bundle:nil];
ViewController *vC2 = [mStoryboard instantiateViewControllerWithIdentifier:#"VC2"];
[self.navigationController pushViewController:vC2 animated:YES];

Resources