App Crashes in UITabBarController delegate method - iphone

Hi
I am trying to add and remove tab bar elements dynamically. There are two arrays. One is shown first with an added tabbaritem with name "More" and other array is added to the tabbar when user presses More. User can come back to first array by pressing Less tabbaritem in second array. Problem is that when i frequently press More and Less tabbaritems in sequence More, Less, More, Less, More, Less - The app crashes after last Less. Array seems ok to me and so is tabbar controller. I am not able to figure out the problem.
Below is the code of tab bar delegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSLog(#"selected view controller is :%#",viewController);
if(viewController.view.tag == -1){
[self.tabBarController setViewControllers:self.level2TabBarItems animated:YES];
[self.tabBarController setSelectedIndex:0];
}else if(viewController.view.tag == -2){
[self.tabBarController setViewControllers:self.level1TabBarItems animated:YES];
[self.tabBarController setSelectedIndex:0];
}
}
Can anyone please let me know where I am doing wrong?
Best Regards

I had similar problem. I guess that you construct new instance of VC in your array, so frequently switching more/less causes calling method from the old instance (is not replaced yet at that moment).
Unfortunatelly setViewControllers method (as documentation say) automatically remove old view controllers calling dealloc and it seems that there is no other way to reuse them.
In your case you can try to disable selecting tabs until tabBarController:didSelectViewController: execute implementing (I didn't test it):
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
self.selectLock = YES;
// your code
self.selectLock = NO;
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
return !self.selectLock;
}

Make comment NSLog here. This is not proper format to print this.

May be your array's are empty. Try to set a breakpoint and you will find the solution which line is causing the crash.

I think Both if and else if are not satisfied with this condition
Just Check your Tag with this NSLog(#"%d",viewController.view.tag);

Related

Back button animation issue in iPhone

I have scenario in that, On click of Tab I am calling viewWillAppear method and but after that when I press Back button It will directly back without any animation.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
switch(mytabbar.selectedIndex)
{
case 0:
[viewController viewWillAppear:YES];
break;
}
}
All thing working fine but I don't get Back button animation is only issue
You are not allowed to call view controller life cycle methods - like viewWillAppear and viewDidLoad. They automatically called throughout the life cycle of a view as and when needed and applicable.
You need to tell us what exactly you want to implement , then we can help you?
On click of back:
- (IBAction)onBackButtonClicked:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}

UITabBarController Weirdness ?

If I normally load up a UITabBarController and switch between views, it calls the viewWillAppear of each view controller.
But it is not so.
I want to switch to another tab as soon as another tab is touched.
If I specify a tab to load up - for example [self.tabBarController setSelectedIndex:0] in the viewWillAppear of one of the tabs (say tab 4)... It goes immediately back to tab 0.
But after that.... it does not call the viewWillAppear on any of the tabs when I switch between them.
For example, if I again go to tab 4, it does not come back to tab 0. I expect it to by a never ending cycle as I expect tab 0 to load up as soon as tab 4 is touch.
But it runs JUST ONCE !!
Why ??
Note: Question has been edited.
I think I found a solution. It works every time you click on your tab and it calls viewWillAppear on both tabs.
You can do this in your AppDelegate (or somwhere else in UITabBarController's delegate):
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
Sample code:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
if([self.tabBarController.viewControllers indexOfObject:viewController] == 1) {
[self.tabBarController setSelectedIndex:0];
}
}
setting the selectedIndex won't change the selectedViewController. You will have to change selectedViewController itself. Look at the documentation for more details.

self.tabBarController.selectedIndex not calling viewDidAppear:YES

In a tabbar view when I call the tab to load useing self.tabBarController.selectedIndex the viewWillAppear is not called If i am been to the tab before hand is there a way to force the view to reload.
self.tabBarController.selectedIndex = 3;
[self.tabBarController.selectedViewController viewDidAppear:YES];
I was also thanking of dumping memory ever time i change tab's and that way when i get back to that view it reloads from the database.
you can implement
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
in the UITabBarControllerDelegate (probably your app delegate). Then in there you can manually call the methods you want on whichever index's viewController you selected.

Remove a view from TabBarController

I'm using a TabBarController to select the first view of that spec. part. From this I've to push other views which have to removed later. Example (ReviewDetailController is an UIViewController):
ReviewDetailController *ctr = [[ReviewDetailController alloc] initWithNibName:#"ReviewDetail" bundle:nil];
... do some initializing and then
self.tabBarController.selectedViewController = ctr;
[ctr release];
This works, but I find no way to go back to the previous view.
Because it is not a navigationController, I can't use pushViewController and later popViewController.
But to push and to pop is what I really need.
I don't know if I did understand this rightly, but maybe you can use this
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController;
Store your topfrontViewController and you can switch between them.
Remember to set the delegate.

iPhone UITabbar item double-click pops controllers

just found out something: If you have a Tabbar combined with a NavigationController (that has some views on it's stack) and you double click the TabBarItem, the view pops to the first ViewController, whether you like it or not.
Is there a way to prevent this?
You probably should not prevent this behavior. It's a standard iPhone UI convention, like tapping the status bar to scroll to the top of a scroll view.
If you really want to do it, you should implement the UITabBarController delegate method -tabBarController:shouldSelectViewController:, like mckeed mentioned. If you have more than five tabs, however, the selectedViewController may be a view controller that is in the "More" section, but vc will be [UITabBarController moreNavigationController]. Here's an implementation that handles that case:
- (BOOL)tabBarController:(UITabBarController *)tbc shouldSelectViewController:(UIViewController *)vc {
UIViewController *selected = [tbc selectedViewController];
if ([selected isEqual:vc]) {
return NO;
}
if ([vc isEqual:[tbc moreNavigationController]] &&
[[tbc viewControllers] indexOfObject:selected] > 3) {
return NO;
}
return YES;
}
I just ran into this problem myself and found a way to do it. Make a delegate for your UITabBarController and implement tabBarController:shouldSelectViewController: to prevent selecting the same controller:
- (BOOL) tabBarController:(UITabBarController *)tbc shouldSelectViewController:(UIViewController *)vc {
return tbc.selectedViewController != vc;
}
You can also add more complicated logic if you only want to prevent it in some cases.
The only way I've found so far is to make a subclass of UINavigationController and overwrite the popToRootViewControllerAnimated method to return nil.
This seems to be the method which the UITabBar calls when tabbed twice. I don't know if it's the correct way though... Would love some feedback on the issue...
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated {
return nil;
}
I agree with keeping this as-intended behavior, but at the same time things get interesting with unwinding the VC stack gracefully (such as when editing a nested series of Core Data objects). In my case, it's tantamount to canceling each VC.
Thus, is there some way for me to know we're popping all the way up to the root VC? I'm thinking a cancel/rollback op during viewWillDisappear doesn't cut it, because that same view would surely disappear after a save as well. I need to somehow broadcast "we're canceling - bail out!" when popping all the way to the root VC in a given tab. Checking a dirty/new flag as a safety check within viewWillDisappear also doesn't help, since that test would then be called twice in the case of a legit cancel (that is, if the cancel button is actually tapped).