Trouble pushing view controller from a welcome screen [closed] - ios

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a welcome screen that only shows the first time the user opens the app. The screen is working great, but I can't get it to show the normal screen when the user clicks done.
Here is the code in the app delegate to create the normal screen -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] ;
if([[NSUserDefaults standardUserDefaults] boolForKey:#"TermsAccepted"]!=YES)
{
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"TermsAccepted"];
}
// Override point for customization after application launch.
FeedViewController *feedViewController = [[FeedViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:feedViewController];
[self.window addSubview:nav.view];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
self.tabBarController = [[UITabBarController alloc] init];
[[UITabBar appearance] setTintColor:[UIColor redColor]];
// FeedViewController
feedViewController=[[FeedViewController alloc] init];
feedViewController.tabBarItem.image=[UIImage imageNamed:#"Describe-Home_Icon_NormalArtboard-1"];
feedViewController.title = #"Timeline";
feedViewController.tabBarItem.title = nil;
//TodayViewController
TodayViewController *todayViewController = [[TodayViewController alloc] init];
todayViewController.tabBarItem.image = [UIImage imageNamed:#"Today_Icon"];
todayViewController.title = #"Today";
todayViewController.tabBarItem.title = nil;
//CreateViewController
self.createViewController = [[CreateViewController alloc] init];
self.createViewController.tabBarItem.image = [UIImage imageNamed:#"Create_Icon"];
self.createViewController.title = #"Create";
self.createViewController.tabBarItem.title = nil;
//AlertViewController
AlertsViewController *alertsViewController = [[AlertsViewController alloc] init];
alertsViewController.tabBarItem.image=[UIImage imageNamed:#"Alerts_IconArtboard-1"];
alertsViewController.title=#"Alerts";
alertsViewController.tabBarItem.title = nil;
//ProfileViewController
ProfileViewController *profileViewController = [[ProfileViewController alloc] init];
profileViewController.tabBarItem.image=[UIImage imageNamed:#"Profile_IconArtboard-1"];
profileViewController.title=#"Profile";
profileViewController.tabBarItem.title = nil;
NSMutableArray *tabBarViewControllers = [[NSMutableArray alloc] initWithCapacity:2];
self.tabBarController = [[UITabBarController alloc] init];
UINavigationController *feedNavigationController = [[UINavigationController alloc] initWithRootViewController:feedViewController];
[tabBarViewControllers addObject:feedNavigationController];
feedNavigationController = nil;
UINavigationController *todayNavigationController = [[UINavigationController alloc] initWithRootViewController:todayViewController];
[tabBarViewControllers addObject:todayNavigationController];
todayNavigationController = nil;
UINavigationController *createNavigationController = [[UINavigationController alloc] initWithRootViewController:self.createViewController];
[tabBarViewControllers addObject:createNavigationController];
createNavigationController = nil;
UINavigationController *alertsNavigationController = [[UINavigationController alloc] initWithRootViewController:alertsViewController];
[tabBarViewControllers addObject:alertsNavigationController];
alertsNavigationController = nil;
UINavigationController *profileNavigationController = [[UINavigationController alloc] initWithRootViewController:profileViewController];
[tabBarViewControllers addObject:profileNavigationController];
profileNavigationController = nil;
self.tabBarController.viewControllers = tabBarViewControllers;
tabBarViewControllers = nil;
[self.window addSubview:self.tabBarController.view];
return YES;
}
In feedViewController to push the welcome view controller -
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"TermsAccepted"]){
NSLog(#"Second time opening the app");
}
else{
WelcomeViewController *welcomeViewController = [[WelcomeViewController alloc] init];
[self.navigationController pushViewController:welcomeViewController animated:NO];
}
To go back to feed that isn't working -
-(void)showDone:(UIButton *)sender {
if (self.navigationItem.rightBarButtonItem.tintColor == [UIColor redColor]) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"TermsAccepted"];
FeedViewController *feedViewController = [[FeedViewController alloc] init];
[[UIApplication sharedApplication] keyWindow].rootViewController = feedViewController;
self.tabBarController.tabBar.hidden = NO;
self.navigationController.navigationBar.hidden = NO;
}
}

It looks like when you show your Welcome screen, you push it onto a UINavigatonController. But when you click Done, you're trying to set the root view controller on the window instead of just popping the view controller from the navigation controller. It also looks like you're creating a new instance of your FeedViewController instead of using the instance you already have created.
Also, have you checked to see if it's even executing the code in your showDone: method? You're using == to compare the tintColor of a UIBarButtonItem with a UIColor, but using == will only return true if they're both the exact same UIColor instance, which they might not be. You'll want to use the method isEqual: to compare two colors, so you would do the following instead:
[self.navigationItem.rightBarButtonItem.tintColor isEqual:[UIColor redColor]]
Note that this won't always return YES for equal colors if they're in different color spaces, but most of the time this should work.
Also, you should consider moving your code out of your app delegate, because generally application:didFinishLaunchingWithOptions: is used only for things that need to be done immediately upon startup. It shouldn't be used to initialize a bunch of view controllers, those should only be initialized when it's time for them to be displayed.

Related

viewControllers that doesn't appear

I have a question for you:
I have a set of UIViewController attached to self.tabBarController.viewControllers
and i have another one alone that is supposed to be the login scree that appear just once (the first time you open the app ever), and i wish to load that one in case the user is not logged in, otherwise or after that the user log in, it will load the full self.tabBarController.viewControllers that i have.
Here is the code:
-(void)load_login_view{
NSLog(#"map");
UIViewController * fb_login = [[FacebookLoginView alloc]init];
fb_login.title = #"fsf ss";
UINavigationController * fb_login_navigation = [[UINavigationController alloc] initWithRootViewController:fb_login];
[fb_login_navigation.tabBarItem setImage:[UIImage imageNamed:#"eventi.png"]];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL login_status = [defaults objectForKey:#"login_status"];
UIViewController * secondpage = [[SecondViewController alloc]init];
secondpage.title = #"second";
UINavigationController * secondpage_navigation = [[UINavigationController alloc] initWithRootViewController:secondpage];
[secondpage_navigation.tabBarItem setImage:[UIImage imageNamed:#"eventi.png"]];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[secondpage_navigation];
self.window.rootViewController = self.tabBarController;
if(!login_status){
[self load_login_view];
}else{
}
[self.window makeKeyAndVisible];
}
You have many ways to do that. There is a couple of examples.
With your current navigation flow
-> if the user is not logged, you can display your login view controller as modal so it will be over top of your tabBarController.
//something like that
-(void)load_login_view{
UIViewController * fb_login = [[FacebookLoginView alloc]init];
fb_login.title = #"fsf ss";
UINavigationController * fb_login_navigation = [[UINavigationController alloc] initWithRootViewController:fb_login];
[self.window.rootViewController presentViewController:fb_login_navigation animated:NO completion:nil];
}
->when you user is logged, dismiss the login controller. If needed, save user data for the next time
->do some work to update the selected controller inside your TabBarcontroller if needed.
Change your navigation flow
-> use UINavigationController with the login Controller ([[UINavigationController alloc] initWithRootViewController:fb_login]) as a rootController for your application
UIViewController * fb_login = [[FacebookLoginView alloc]init];
fb_login.title = #"fsf ss";
UINavigationController * fb_login_navigation = [[UINavigationController alloc] initWithRootViewController:fb_login];
self.window.rootViewController = fb_login_navigation;
-> when you user is logged, push to your TabBarcontroller. If needed, save user data for the next time
//inside fb_login controller ( you can optimize the code, it's just a quick example)
UIViewController * secondpage = [[SecondViewController alloc]init];
secondpage.title = #"second";
UINavigationController * secondpage_navigation = [[UINavigationController alloc] initWithRootViewController:secondpage];
[secondpage_navigation.tabBarItem setImage:[UIImage imageNamed:#"eventi.png"]];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[secondpage_navigation];
[self.navigationController pushViewController:tabBarController animated:YES];
->To avoid the double navigationBar (fb_login_navigation / secondpage_navigation), you can hide the navigation of fb_login_navigation when needed.
-> the next time, if the user is logged, you can fire the code above just after loading the login controller instead of waiting that the user enters his credentials.
Hope it helps.

Button to Present ViewController After Tutorial (which Loads For 1st Time Only)

I have a tutorial ViewController called tutorialViewController which only presents itself for the first time the app is launched. This is how I do that:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL hasRunBefore = [defaults boolForKey:#"FirstRun"];
if (!hasRunBefore) {
[defaults setBool:YES forKey:#"FirstRun"];
self.window.rootViewController = [tutorialViewController new];
self.window.backgroundColor = [UIColor whiteColor];
// RESideMenu Stuff that Must Be Done
leftSideMenuViewController *leftMenuViewController = [[leftSideMenuViewController alloc] init];
rightSideMenuViewController *rightMenuViewController = [[rightSideMenuViewController alloc] init];
musicPlayerViewController *navigationController = [[homeViewController alloc] init];
RESideMenu *sideMenuViewController = [[RESideMenu alloc] initWithContentViewController:navigationController
leftMenuViewController:leftMenuViewController
rightMenuViewController:rightMenuViewController];
sideMenuViewController.menuPreferredStatusBarStyle = 1;
sideMenuViewController.delegate = self;
sideMenuViewController.contentViewShadowColor = [UIColor blackColor];
sideMenuViewController.contentViewShadowOffset = CGSizeMake(0, 0);
sideMenuViewController.contentViewShadowOpacity = 0.6;
sideMenuViewController.contentViewShadowRadius = 12;
sideMenuViewController.contentViewShadowEnabled = YES;
self.window.backgroundColor = [UIColor blackColor];
}
else
{
NSLog (#"Not the first time this controller has been loaded");
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[[homeViewController alloc] init]];
// RESideMenu Stuff that Must Be Done
leftSideMenuViewController *leftMenuViewController = [[leftSideMenuViewController alloc] init];
rightSideMenuViewController *rightMenuViewController = [[rightSideMenuViewController alloc] init];
RESideMenu *sideMenuViewController = [[RESideMenu alloc] initWithContentViewController:navigationController
leftMenuViewController:leftMenuViewController
rightMenuViewController:rightMenuViewController];
sideMenuViewController.menuPreferredStatusBarStyle = 1;
sideMenuViewController.delegate = self;
sideMenuViewController.contentViewShadowColor = [UIColor blackColor];
sideMenuViewController.contentViewShadowOffset = CGSizeMake(0, 0);
sideMenuViewController.contentViewShadowOpacity = 0.6;
sideMenuViewController.contentViewShadowRadius = 12;
sideMenuViewController.contentViewShadowEnabled = YES;
self.window.rootViewController = sideMenuViewController;
self.window.backgroundColor = [UIColor blackColor];
}
This works well so far - if I load the app for the first time, it shows tutorialViewController. If I close it and open it again, it shows homeViewController.
I'd just like to know how to add an IBAction to take me from tutorialViewController to homeViewController. Currently, I wrote this:
- (IBAction)goToHomeViewController:(id)sender {
homeViewController *navigationController = [homeViewController new];
[self presentViewController:navigationController animated:YES completion:^{
}];
NSLog(#"Start button pressed");
}
It presents homeViewController but it does not show the navigation bar, etc. - as it would if homeViewController was the rootViewController.
Here are some more details
tutorialViewController does not show a status bar or a navigation bar. It is simply a scrollview that takes up the whole screen.
'homeViewControllerhas a navigation bar with a left bar button and right bar button that brings up otherviewControllers`.
I've searched other SO questions but they are mostly to do with Storyboards, which I am not using. Just .xibs (and .h and .m).
How do I present homeViewController from tutorialViewController just as it would display if homeViewController was the rootViewController?
Wrap homeViewController in a UINavigationController should work.
[self presentViewController:[[UINavigationController alloc] initWithRootViewController:homeViewController] animated:YES: completion:nil]
You can also do like this.
In your 'if' condition add tutorialViewController as
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[[tutorialViewController alloc] init]];
And in the goToHomeViewController function add,
homeViewController *navigationController = [homeViewController new];
[self.navigation pushViewController:navigationController animated:NO];
So first time the tutorialViewController act as rootview controller and if you want to hide NavigationBar add following code,
[[self navigationController] setNavigationBarHidden:YES animated:YES];

how to add tab bar controller from the second view controller [duplicate]

This question already has an answer here:
Showing login view controller before main tab bar controller
(1 answer)
Closed 9 years ago.
Im beginner to IOS app development learning.
I have a login screen as my first view controller and i need the second view controller to be a tab bar view controller .with 4 different tabs and i have 4 different XIB's for them.
some one help me to go ahead.
Best way you can do is Present the login screen modally when the app starts from your tab bar controller first screen, add code for presenting login screen in viewWillAppear and after login dismiss the screen. You can create TabBarController in appDelegate like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UITabBarController tabBarController=[[UITabBarController alloc] init];
FirstViewController *firstVC = [[UIViewController alloc] initWithNibName:#"FirstVC" bundle:nil];
UINavigationController *firstNavController = [[UINavigationController alloc] initWithRootViewController: firstVC];
SecondViewController *secondVC = [[UIViewController alloc] initWithNibName:#"secondVC" bundle:nil];
UINavigationController *secondNavController = [[UINavigationController alloc] initWithRootViewController:secondVC];
tabBarController.viewControllers = [NSArray arrayWithObjects: firstNavController, secondNavController, nil];
tabBarController.selectedIndex=0;
tabBarController.delegate = self;
UITabBarItem *item1 = [[UITabBarItem alloc] initWithTitle:#"Movies" image:[UIImage imageNamed:#"MoviesTAB.png"] tag:1];
[firstVC setTabBarItem:item1];
UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:#"Music" image:[UIImage imageNamed:#"musicTAB.png"] tag:2];
[seconfVC setTabBarItem:item2];
tabController.tabBar.translucent = NO;
tabController.tabBar.barStyle = UIBarStyleBlack;
tabBarController.tintColor = [UIColor whiteColor];
self.window.rootViewController = tabController;
return YES;
}
Best way is use storyboard and there just have one initial UIViewController and from that make segue to UITabBarViewController.
http://youtu.be/a_DCTSTv1Mw
If you want to make it through xib make a UITabBarViewController and add viewControllers to the array of object of that UITabBarViewController's object.
Sample code :
NSMutableArray *arrViewControllers = [[NSMutableArray alloc] init];
UIViewController *tabController;
UIImage *tabImage ;
NSString *tabTitle;
for (int i= 0; i < 3; i++) {
switch (i) {
case 0:
tabController = [[ViewController alloc] init];
tabImage = [UIImage imageNamed:#"icon1.png"];
tabTitle = #"Text";
break;
case 1:
tabController = [[ImageDemoViewController alloc] init];
tabImage = [UIImage imageNamed:#"icon2.png"];
tabTitle = #"Image";
break;
case 2:
tabController = [[TableDemoViewController alloc] init];
tabImage = [UIImage imageNamed:#"icon3.png"];
tabTitle = #"Table";
break;
}
// set the image and title using some properties of UIViewController
tabController.tabBarItem.image = tabImage;
tabController.tabBarItem.title = tabTitle;
//add objects to array
[arrViewControllers addObject:tabController];
[tabController release];
}
_baseController = [[UITabBarController alloc] init];
_baseController.viewControllers = arrViewControllers;
[arrViewControllers release];
go to your appDelegate
1.create a viewController for login screen.
LoginViewController *viewController1 = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
2.create a navigationController with root view your login ViewController.
UINavigationController *nVC = [[UINavigationController alloc] initWithRootViewController:viewController1];
3.make navigationController to root view of window.
self.window.rootViewController = self.nVC;
[self.window makeKeyAndVisible];
Now go to Touch-Up-Inside method of login button in LoginViewController.
1.After validation of password and userId initialise your viewControllers for tabbar and TabbarViewController.
UiViewController ...*yourViewControllers,..,
UITabBarController *YourtabBarController = [[UITabBarController alloc] init];
2.Now add these viewControllers to your tabbarController.
YourtabBarController.viewControllers = #[ YourViewController1,YourViewController2,YourViewController3,......];
3.Finally push this tabbarController to navigationControllere.
[self.navigationController pushViewController:YourtabBarController animated:NO];

iOS App with multiple view controllers

My current application on appDelegate loads a main.xib screen which only contains an two images background and logo. This screen behind code determines if the user is logged on the system if not it will show the login else it will show the dashboard.
The application has been created as a single view application, sample code of the appDelegate:
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
self.Main = [[vcMain alloc] initWithNibName:#"vcMain" bundle:nil];
self.window.rootViewController = self.Main;
[self.window makeKeyAndVisible];
}
else
{
self.MainiPad = [[vcMain_iPad alloc] initWithNibName:#"vcMain_iPad" bundle:nil];
self.window.rootViewController = self.MainiPad;
[self.window makeKeyAndVisible];
}
On the Main.m I have the following on the viewDidLoad:
if (islogged)
{
vcDashboard *vcDash = [[vcDashboard alloc] initWithNibName:#"vcDashboard" bundle:nil];
_ncMain = [[UINavigationController alloc] initWithRootViewController:vcDash];
_ncMain.navigationBar.barStyle = UIBarStyleBlackOpaque;
_ncMain.view.frame = self.view.bounds;
[self.view addSubview:_ncMain.view];
ViewActive = vDash;
}
else
{
vcLogin *login = [[vcLogin alloc] initWithNibName:#"vcLogin" bundle:nil];
login.modalPresentationStyle = UIModalPresentationFormSheet;
login.view.frame = self.view.bounds;
[self presentViewController:login animated:YES completion:nil];
}
There is a menu button available on the Dashboard that presents the user with a series of options to select another screen and when pressed it will activate the following method:
- (void)displayView:(NSString *)strView Notification:(NSNotification *)notification{
if(_ncMain)
{
[_ncMain.view removeFromSuperview];
_ncMain = nil;
}
if ([strView isEqual: #"Dashboard"])
{
vcDashboard *vcDash = [[vcDashboard alloc] initWithNibName:#"vcDashboard" bundle:nil];
_ncMain = [[UINavigationController alloc] initWithRootViewController:vcDash];
_ncMain.navigationBar.barStyle = UIBarStyleBlackOpaque;
_ncMain.view.frame = self.view.bounds;
[self.view addSubview:_ncMain.view];
ViewActive = vDash;
}
else if ([strView isEqual: #"Catalog"])
{
vcCatalog *vcCat = [[vcCatalog alloc] initWithNibName:#"vcCatalog" bundle:nil];
_ncMain = [[UINavigationController alloc] initWithRootViewController:vcCat];
_ncMain.navigationBar.barStyle = UIBarStyleBlackOpaque;
_ncMain.view.frame = self.view.bounds;
[self.view addSubview:_ncMain.view];
ViewActive = vCatalog;
}
else if ([strView isEqual: #"News"])
{
vcNews *vcNew = [[vcNews alloc] initWithNibName:#"vcNews" bundle:nil];
_ncMain = [[UINavigationController alloc] initWithRootViewController:vcNew];
_ncMain.navigationBar.barStyle = UIBarStyleBlackOpaque;
_ncMain.view.frame = self.view.bounds;
[self.view addSubview:_ncMain.view];
ViewActive = vNews;
}
}
My doubt here is I don't seem to know if this is the correct way of changing between screens when an option is selected from this menu and if is right to always addSubview to the principal screen. Don't know if using the navigationcontroller template is a solution. I'm concern of the memory consumed by the app when doing all of this, also I'm currently using ARC on the project.
I recommend you that avoid the addSubview method if possible. UiNAvigationController offer you a good way to handle different viewControllers. If you make addSubview the changeRotation event, for example, is not called. And when you make a pop the viewController is dealloced.
Good luck!

xCode 4.2 UITableView drilldown

I'm a newbie to the xCode world and I had a few questions regarding my application setup.
My application a list of Authors, click on author and get author detail plus book titles, and then click on the book title and get book information, but I'm unable to figure out the show detail part.
I have established a tab view controller that displays UIViewControllers in the window.
//create view controllers
UIViewController *vc1 = [[HomeViewController alloc] init];
UIViewController *vc2 = [[AuthorViewController alloc] init];
UIViewController *vc3 = [[BooksViewController alloc] init];
UIViewController *vc4 = [[GenreViewController alloc] init];
UIViewController *vc5 = [[UserViewController alloc] init];
//create instance of tab bar
self.tabBar = [[UITabBarController alloc] init];
//add views to tab bar
self.tabBar.viewControllers = [NSArray arrayWithObjects:vc1,vc2,vc3, vc4, vc5, nil];
self.window.rootViewController = self.tabBar;
//self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
//self.window.backgroundColor = [UIColor whiteColor];
[_window addSubview:_tabBar.view];
[self.window makeKeyAndVisible];
return YES;
This works perfectly. My first view "AuthorViewContoller" is a table and I can display data, however I can NOT get the detailController to show.
My AuthorViewController viewDidLoad method
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.author= [[NSArray alloc] initWithObjects:#"One", #"two", nil];
self.detailController = [[AuthorDetailController alloc] init];
and my methoddidSelectRowAtIndexPath:
if(indexPath.row == 0)
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
AuthorDetailController *dc = [[AuthorDetailController alloc] initWithNibName:#"AuthorDetailController" bundle:nil];
dc.title = [author objectAtIndex:indexPath.row];
[self.navigationController pushViewController:dc animated:YES];
}else{
[self.navigationController pushViewController:detailController animated:YES];
}
I'm declaring detailController in my AuthorViewController.h file.
#property (nonatomic, retain) IBOutlet AuthorDetailController *detailController;
You have to actually create a UINavigationController, and have it be part of your controller hierarchy, before you can use pushViewController:animated:. You should really try setting this up in a NIB, instead of code, but in your code you can try this in place of your current vc2 initialization:
UIViewController *vc2 = [[UINavigationController alloc] initWithRootViewController:[[AuthorViewController alloc] init]];

Resources