Unbalanced calls to begin/end appearance transitions for UITabBarController - iphone

I have an UITabBarController, when initial run, I want to overlay a login view controller but received error.
Unbalanced calls to begin/end appearance transitions for < UITabBarController: 0x863ae00 >.
Below is the code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *lessonVC = [[[LessonViewController alloc] initWithNibName:#"LessonViewController" bundle:nil] autorelease];
UIViewController *programVC = [[[ProgramViewController alloc] initWithNibName:#"ProgramViewController" bundle:nil] autorelease];
UIViewController *flashcardVC = [[[FlashCardViewController alloc] initWithNibName:#"FlashCardViewController" bundle:nil] autorelease];
UIViewController *moreVC = [[[MoreViewController alloc] initWithNibName:#"MoreViewController" bundle:nil] autorelease];
UINavigationController *lessonNVC = [[[UINavigationController alloc] initWithRootViewController:lessonVC] autorelease];
UINavigationController *programNVC = [[[UINavigationController alloc] initWithRootViewController:programVC] autorelease];
UINavigationController *flashcardNVC = [[[UINavigationController alloc] initWithRootViewController:flashcardVC] autorelease];
UINavigationController *moreNVC = [[[UINavigationController alloc] initWithRootViewController:moreVC] autorelease];
self.tabBarController = [[[UITabBarController alloc] init/*WithNibName:nil bundle:nil*/] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:lessonNVC, programNVC, flashcardNVC, moreNVC, nil];
self.tabBarController.selectedIndex = 0;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
if (![[ZYHttpRequest sharedRequest] userID])
{
// should register or login firstly
LoginViewController *loginVC = [[LoginViewController alloc] initWithNibName:#"LoginViewController"
bundle:nil];
loginVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.tabBarController presentModalViewController:loginVC animated:YES];
ZY_SAFE_RELEASE(loginVC);
}
return YES;
}
Anyone who can help me? Thanks in advance!

You need to wait to present the modal view controller until the next run loop. I ended up using a block (to make things more simple) to schedule the presentation for the next run loop:
Update:
As mentioned by Mark Amery below, just a simple dispatch_async works, there's no need for a timer:
dispatch_async(dispatch_get_main_queue(), ^(void){
[self.container presentModalViewController:nc animated:YES];
});
/* Present next run loop. Prevents "unbalanced VC display" warnings. */
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.container presentModalViewController:nc animated:YES];
});

I suspect the problem is that you're trying to call presentModalViewController: before the tab bar is done loading. Try moving the final logic onto the next event loop:
[self.window makeKeyAndVisible];
[self performSelector:(handleLogin) withObject:nil afterDelay:0];
}
- (void)handleLogin
{
if (![[ZYHttpRequest sharedRequest] userID])
{
// should register or login firstly
LoginViewController *loginVC = [[LoginViewController alloc] initWithNibName:#"LoginViewController"
bundle:nil];
loginVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.tabBarController presentModalViewController:loginVC animated:YES];
ZY_SAFE_RELEASE(loginVC);
}
}

[self.tabBarController presentModalViewController:loginVC animated:**NO**];

I had a similar problem when tried to presentModalViewController (my welcome screen) in main view's viewWillAppear. Is was solved just by moving the modal VC call to viewDidAppear.

[self performSelector:#selector(modaltheView) withObject:self afterDelay:0.1];
-(void)modaltheView
{
[self.container presentModalViewController:nc animated:YES];
}

Related

How to go back to previous view controller using custom back button?

I am new to iOS development. I am going to next screen using following statement.
locationViewController = [[LocationViewController alloc] initWithNibName:#"LocationViewController" bundle:nil];
[navigationController pushViewController:locationViewController animated:YES];
Now I want to go back to previous screen by tapping on custom back button on the top bar of the current screen.
use this:
-(IBAction)back:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
For home button:
NSArray *viewContrlls=[[self navigationController] viewControllers];
for( int i=0;i<[ viewContrlls count];i++)
{
id obj=[viewContrlls objectAtIndex:i];
if([obj isKindOfClass:[Rate_O_MeterViewController class]])
{
[[self navigationController] popToViewController:obj animated:YES];
return;
}
}
in place of Rate_O_MeterViewController give your controller name...add it in action of home button.
Try this,
appDelegate.m - didFinishLaunchingWithOptions method
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil] autorelease];
//-----------navigation view--------------
UINavigationController *navHomeController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = navHomeController;
Create a Back button:
UIBarButtonItem * backButton=[[UIBarButtonItem alloc]initWithTitle:#"Back" style:UIBarButtonItemStyleDone target:self action:#selector(goBack:)];
self.navigationItem.leftBarButtonItem=backButton;
And write a function:
-(void)goBack:(id)sender
{
[self.navigationController popViewControllerAnimated:YES]
}

navigationcontroller title and button

In my tab based application delegate i added the navigation controller as like the following,
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
UIViewController *viewController3 = [[view1 alloc] initWithNibName:#"view1" bundle:nil];
UIViewController *viewController4 = [[view2 alloc] initWithNibName:#"view2" bundle:nil];
UIViewController *viewController5 = [[view3 alloc] initWithNibName:#"view3" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[viewController1, viewController2,viewController3,viewController4,viewController5];
navigationController=[[UINavigationController alloc]initWithRootViewController:self.tabBarController];
[self.window addSubview:[navigationController view]];
self.window.rootViewController = self.navigationController;
i would not be able to added the title in each view. While adding it doesn showing the title?Pls help me to resolve this issue
use bellow code...
Here i add UINavigationController to every tab and also assign title for tab and also for UINavigationBar like bellow...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
UIViewController *viewController1, *viewController2, *viewController3, *viewController4, *viewController5;
UINavigationController *navviewController1 , *navviewController2, *navviewController3, *navviewController4, *navviewController5;
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
viewController1 = [[[YourViewController1 alloc] initWithNibName:#"YourViewController1" bundle:nil] autorelease];
navviewController1=[[UINavigationController alloc]initWithRootViewController:viewController1];
navviewController1.title = #"Home";
// navviewController1.navigationBarHidden=YES;
viewController2 = [[[YourViewController2 alloc] initWithNibName:#"YourViewController2" bundle:nil] autorelease];
navviewController2=[[UINavigationController alloc]initWithRootViewController:viewController2];
// navviewController2.navigationBarHidden=YES;
navviewController2.title = #"HowItsWork";
viewController3 = [[[YourViewController3 alloc] initWithNibName:#"YourViewController3" bundle:nil] autorelease];
navviewController3=[[UINavigationController alloc]initWithRootViewController:viewController3];
// navviewController3.navigationBarHidden=YES;
navviewController3.title = #"Join Us";
viewController4 = [[[YourViewController4 alloc] initWithNibName:#"YourViewController4" bundle:nil] autorelease];
navviewController4=[[UINavigationController alloc]initWithRootViewController:viewController4];
// navviewController4.navigationBarHidden=YES;
navviewController4.title = #"Become";
viewController5 = [[[YourViewController5 alloc] initWithNibName:#"YourViewController5" bundle:nil] autorelease];
navviewController5=[[UINavigationController alloc]initWithRootViewController:viewController5];
// navviewController4.navigationBarHidden=YES;
navviewController5.title = #"Contact Us";
self.tabBarController.viewControllers = [NSArray arrayWithObjects:navviewController1, navviewController2,navviewController3,navviewController4,navviewController5, nil];
self.window.rootViewController = self.tabBarController;
}
[self.window makeKeyAndVisible];
}
2)OR
Also you can simple assign title in your particular class like bellow...
-(void)viewWillAppear:(BOOL)animated{
self.title = #"yourTitle";
}
i hope this helpful to you...
Go to viewdidload method in every tabbar controller & use line:
navigationController.title=#"hello";
In every viewcontroller viewdidload
self.navigationcontroler.title=#"firstVC";
"title" is the property of UIViewController and UINavigationController is the subclass of UIViewController you can also access it object of UINavigationController, just like navviewController.title = #"myTitle"; and for more detail check Apple Docs. Hope it will help. Cheers
You have added TabBar Controller inside a Navigation Controller so you cannot add title and arises this issue.
Try to add each navigation controller with View controller inside tabbar controller.
I mean add ur ViewController as a root View controller of navigation controller then add to tab Bar controller.
viewController1 = [[[YourViewController1 alloc] initWithNibName:#"YourViewController1" bundle:nil] autorelease];
navviewController1=[[UINavigationController alloc]initWithRootViewController:viewController1];
Now then ad this navigation controller inside to tabbar controller. Do this for all other viewcontrollers

Should I use an individual UINavigationController per Tab Bar

According to Apple, I can combine UINavigationController and UITabBarController using the code, e.g.
MyViewController1* vc1 = [[MyViewController1 alloc] init];
MyViewController2* vc2 = [[MyViewController2 alloc] init];
MyViewController3* vc3 = [[MyViewController3 alloc] init];
MyNavRootViewController* vc4 = [[MyNavRootViewController alloc] init];
UINavigationController* navController = [[UINavigationController alloc]
initWithRootViewController:vc4];
NSArray* controllers = [NSArray arrayWithObjects:vc1, vc2, vc3, navController, nil];
tabBarController.viewControllers = controllers;
In this setup, only vc4 has the UINavigationController, but what if I want vc1-vc3 also has the UINavigationController?, should I do like..
MyViewController1* vc1 = [[MyViewController1 alloc] init];
UINavigationController* nv1 = [[UINavigationController alloc]
initWithRootViewController:vc1];
MyViewController1* vc2 = [[MyViewController2 alloc] init];
UINavigationController* nv2= [[UINavigationController alloc]
initWithRootViewController:vc2];
MyViewController1* vc3 = [[MyViewController3 alloc] init];
UINavigationController* nv3 = [[UINavigationController alloc]
initWithRootViewController:vc3];
NSArray* controllers = [NSArray arrayWithObjects:nv1, nv2, nv3, nil];
tabBarController.viewControllers = controllers;
Is this the right approach?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [self initializeTabBarItems];
self.navigationController = [[UINavigationController alloc]init];
[self.navigationController setNavigationBarHidden:YES];
self.window.rootViewController = self.navigationController;
[self.navigationController pushViewController:_tabBarController animated:YES];
[self.window makeKeyAndVisible];
return YES;
}
- (NSArray *)initializeTabBarItems
{
NSArray * retval;
/* Initialize view controllers */
UIViewController *viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil] autorelease];
UIViewController *viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil] autorelease];
UIViewController *viewController3 = [[[ThirdViewController alloc]initWithNibName:#"ThirdViewController" bundle:nil]autorelease];
UIViewController *viewController4 = [[[FourthViewController alloc] initWithNibName:#"FourthViewController" bundle:nil] autorelease];
UIViewController *viewController5 = [[[FivfthViewController alloc] initWithNibName:#"FivfthViewController" bundle:nil] autorelease];
/* Initialize navigation controllers */
UINavigationController * navigationController1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
UINavigationController * navigationController2 = [[UINavigationController alloc] initWithRootViewController:viewController2];
UINavigationController * navigationController3 = [[UINavigationController alloc] initWithRootViewController:viewController3];
UINavigationController * navigationController4 = [[UINavigationController alloc] initWithRootViewController:viewController4];
UINavigationController * navigationController5 = [[UINavigationController alloc] initWithRootViewController:viewController5];
/* Release View Controllers */
[viewController1 release];
[viewController2 release];
[viewController3 release];
[viewController4 release];
[viewController5 release];
/* Stuff Navigation Controllers into return value */
retval = [NSArray arrayWithObjects:viewController1,viewController2,viewController3,viewController4,viewController5,nil];
/* Release Navigation Controllers */
[navigationController1 release];
[navigationController2 release];
[navigationController3 release];
[navigationController4 release];
[navigationController5 release];
return (retval);
}
You Can Try This ....
Yes Howard, your approach is fine. Apple says this too. I also follow same approach while working with UITabbarController with UINavigationController and it works great for me.
You should have one UINavigationController per tab of your TabBarController. So your 2nd approach is correct. I don't think that you can reuse the same navigation controller for all the tabs.
Yes your approach is correct.
If u have to navigate views into tab then that tab should have navigation Controller.
UINavigationController * navigationCtrl = [[UINavigationController alloc] initWithRootViewController:firstTabViewCtrl];
[arrTabs addObject:navigationCtrl];
Either wise there is no need of navigation Controller inside tab.
[arrTabs addObject:firstTabViewCtrl];

iOS tab bar not show modal view

I want to show modal view in the start of the app but it doesn't appear. This is my code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self initDataBase];
CustomerModel *customer = [[[CustomerPersistor alloc] init] getLoggedCustomer];
self.window.rootViewController = self.tabBarController;
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *profileViewController = [[[ProfileViewController alloc] initWithNibName:#"ProfileViewController" bundle:nil] autorelease];
profileViewController.title = #"Profile";
UINavigationController *profileNavigation = [[[UINavigationController alloc] initWithRootViewController:profileViewController] autorelease];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:profileNavigation, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
if(customer == nil) { NSLog(#"HO");
ViewController *login = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
//login.delegate = self.tabBarController.view;
[self.viewController presentModalViewController:[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil] animated:YES];
}
return YES;
}
How can I fix it?
First, there doesn't appear to be a self.viewController property that is set, and you're instantiating the same "ViewController" twice. This is all wrong:
ViewController *login = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
//login.delegate = self.tabBarController.view;
[self.viewController presentModalViewController:[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil] animated:YES];
Try moving this code to your viewDidLoad of your profileViewController...i.e. let the TabBarController load along with its first tab's view controller.
Initiate an instanse from the model view like this:
modelView = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
Please follow the list below:
Set the viewController model presented style
[modelView setModalPresentationStyle:UIModalPresentationPageSheet];
Then present it using:
[self.viewController presentModalViewController:floorView animated:YES];
Then, set the size and location of the model controller like this:
modelView.view.superview.bounds = CGRectMake(0, 0, 700, 550);//it's important to do this after presentModalViewController
modelView.view.superview.center = self.view.superview.center;//self.view assumes the base view is doing the launching, if not you might need self.view.superview.center etc.
Hope this help you.

how to add navigationcontroller to uiviewcontroller

employeeDetailed = [[[EmployeeDetailedViewController alloc] initWithNibName:#"EmployeeDetailedViewController" bundle:nil] autorelease];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:employeeDetailed] autorelease];
[employeeDetailed release];
[self.navigationController pushViewController:navController animated:YES];
I try this its saying bad access.[crash]
how to reslove this issue.
# thanks in advance
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Set the view controller as the window's root view controller and display.
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:self.viewController] autorelease];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
employeeDetailed = [[[EmployeeDetailedViewController alloc] initWithNibName:#"EmployeeDetailedViewController" bundle:nil] autorelease];
[self. navigationController presentModalViewController: navController];
This will work for you try this.
You have autorelease set in the first line (alloc/init)
You are then explicitly releasing the view controller on line three.
You are therefore over-releasing this object and causing the crash.
You can remove the [employeeDetailed release] line and it will be fine.
You cannot add UINavigationController to existed navigation stack. Instead of you need to show new navigation controller modal like this:
employeeDetailed = [[[EmployeeDetailedViewController alloc] initWithNibName:#"EmployeeDetailedViewController" bundle:nil] autorelease];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:employeeDetailed] autorelease];
[self presentModalViewController: navController];
The Best Way I found to present Navigation Controller in a specific part in your Application is like these:
MyViewController *myViewController = [[MyViewController alloc]initwithnibname :#"MyViewController"];
UINavigationController *myNavC = [[UINavigationController alloc]initWithRootViewController:myViewController];
Then in your myViewController.m
use
[self.NavigationController pushViewController: XController animated:YES];