I'm newbie in iOS App Dev. I'm working on application having tabbar whose default tabindex is 2.
My problem is: When push notification arrive (in background state of app) after clicking on notification, my app open up on tab 2 and show an alertview. After clicking button of alertview I want to change the selectedTab to 3. Im writing below code in appDelegate in alertView:clickedButtonAtIndex:, everything works fine.
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"story_iphone" bundle:nil];
TabBarController * tb = [sb instantiateViewControllerWithIdentifier:#"TabBarController"];
[[tb.viewControllers firstObject] viewWillAppear:YES];
[tb viewWillAppear:YES];
[tb setSelectedIndex:3];
self.window.rootViewController = tb;
But im facing following problems:
1) ViewWillAppear of that VC (say vc1) is not called.
2)Also after pushing vc2 from vc1, viewWillAppear of VC2 is not called.
3) Poping back to VC1, ViewDidDisappear, ViewWillDisappear of VC2 is not called.
I have searched a lot but im unable to get where im lacking.
Please help me. Thanks in Advance.
Assuming UINavigationController is rootViewController of your app and you are pushing TabBarController to its navigation stack, this should work fine
EDIT
From your comments its clear that, you have tab bar controller in your navigation stack at position 1 rather than at 0 :) Hence now look for viewController at index 1.
(self.window?.rootViewController as! UINavigationController).viewControllers[1] as! UITabBarController).selectedIndex = your_index_value
Suggestion :
Though above mentioned solution works by the virtue that, tab bar controller is at index 1, but the position of tab bar controller in navigation stack may vary at some point if you decide to modify navigation stack itself.
Rather than hard coding the index value, what you can do is, in your app delegate have a variable named tab bar controller and make it public :) now once you create a tab bar controller before pushing it to navigation stack now hold the reference to it :)
Because app delegate is singleton and public property of it is accessible to all the viewControllers, now you can access it directly using app delegate.tabBarController :)
Now who cares where is it navigation stack :) Now you have the reference to the tab bar use it happily :) Happy coding :)
You're not supposed to directly call viewWillAppear, or reload the tab bar controller since you have it already loaded with tab number 2 selected.
All you need to do is something like
[((UITabBarController*)self.window.rootViewController) setSelectedIndex:3];
in the alert handler.
Related
I've read several posts about this issue, but I've been troubleshooting and the previous solutions don't seem to do the trick (i.e. the solutions specify embedding only the parent controller in the navigation controller, which I've tried). To address it as per previous posts, I've removed the embedding of the other views in their own navigation controllers -- but can't then seem to physically draw the segue from one table view to another; or it doesn't show the back button...
Basically, the "Back" button disappears on segue. It isn't seen in the second TableViewController and the last ViewController (on the end). It reappears in the parent, obviously.
EDIT: When I remove the navigation controller from the other two views, then no navigation bar appears on those VCs at all. The bar completely disappears, although it appears on the first one. This is how I have it configured now.
New Storyboard
Navigation Controller follows the Stack theory. When you push something in the stack it will increment the top index count by 1 and pop something in the stack it will decrease the top index count by 1.
In the navigation controller, first controller will be your root viewController. Now When you push new view controller in navigation controller, your top index count will be 2. But you are not pushing the viewController in same navigation controller (let say Stack1) you are creating the new Navigation controller (let say Stack2).
So here you are setting the new controller as the root viewController for new navigation controller(Stack2) and there are no item to pop yet that is why it's not showing the back button.
To Solve these Problem remove the navigation controller from the second and third view controller.
To push you can use segue or you can do it programmatically.
Swift
let vc2 = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController2") as? ViewController2
self.navigationController?.pushViewController(vc2!, animated: true)
Objective C
ViewController2 *vc2 = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
[[self navigationController] pushViewController:vc2 animated:YES];
Navigation Controller Guideline
Edit
if you are not able to see the navigation bar on second VC
Make sure you are not hiding it by code in second VC.
Make sure you are pushing the second VC not presenting the VC.
Select VC in Interface Builder -> Attribute Inspector -> Top bar should be inferred.
if you are using segue then segue type(kind) should be Show.
I´m making an application that have an wizard at the first time the app runs.
After that, it should present a UITabBarController.
The second time the user runs the app, it should just present the UITabBarController.
Since UITabBarController should be the rootViewController, is there a way to redefine the app rootViewController so, when the wizard ends, the TabBarController shows up??
Or is there a better way to accomplish that behavior?
Thanks!!
Yes, you can redefine the window's root view controller from any controller that's currently displayed. You get the reference to the window with self.view.window. So, when your wizard ends, just instantiate your tab bar controller and change the root:
UITabBarController *tbc = [self.storyboard instantiateViewControllerWithIdentifier:#"tbc"]; // or other instantiation method if not using a storyboard
self.view.window.rootViewController = tbc;
In the app delegate, put logic that determines whether this is the first run of the app, and if not, run this slightly modified code to launch the tab bar controller directly:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UITabBarController *tbc = [sb instantiateViewControllerWithIdentifier:#"tbc"]; // or other instantiation method if not using a storyboard
self.window.rootViewController = tbc;
Use an unwind segue. When presenting your application, push UITabBarController onto the navigation stack. If this is the first run of your app, disable animation when pushing the tab bar controller, and push the first screen of your wizard on top of it. If it is not the first run, push the tab bar controller with animation.
When the user goes through the wizard to completion, use an unwind segue to go back to the tab bar controller.
In my project I have 1 viewController which is being pushed with a "modal push" from all other viewControllers. I am trying to add a UINavigationItem (bar at the top) to it, but it is not working. I have a similar viewController at another place in my project and as far as I can see, I have done exactly the same thing with it and being able to add UINavigationItem to it?
Now I need help understanding WHY I am unable to add UINavigationItem to my viewController? I am trying with the following code:
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:self.nextButton, self.menuButton, nil];
I am not getting any errors or ANY indication of why it is not working on my viewController, simply nothing happens? Here is a screen of it: http://tinypic.com/view.php?pic=2itisgp&s=6
The viewController is connected both to a tabBar and UINavigationController but it should not matter since I have decided to push it with "modal" ? If I use a normal "push" the UINavigationItem will appear and it will be linked to the rest of the app. But that is the problem, I want it to be a single slide with its own UINavigationBar(Item, controller) or whatever you call it. The reasoning behind this is far more complex to be explained here and will just bore people. So lets focus on WHY I am unable to add UINavigationItem(bar, controller) at this viewController when using "Modal push" ?????? Please enlighten me if you know anything!
One easy way to accomplish that:
UINavigationController *navigationController = [[UINavigationController alloc]initWithRootController:yourViewController];
[viewController presentModalViewController:navigationController animated:YES];
If you are using Storyboard, you have to embed a Navigation Controller directly to the presented modal controller (Editor > Embed in > Navigation Controller)
Your Storyboard should looks like this :
FirstVC -> Navigation Controller -> SecondVC
I have tab bar and in view "A" and in "A" I have navigation controller. SO inside my navigation controller in "A" i called
[self presentModalViewController:modalView animated:YES]
But modalView shows under tab bar. How to show it above tab bar?
Try to present modal view from UITabBarController:
[self.tabBarController presentModalViewController:modalView animated:YES];
My case, the modal has a transparent background, I set modalPresentationStyle is .overFullScreen and it show at above tabbar with clear background.
In my case the presented view controller had UIModalPresentationStyle.CurrentContext at .modalPresentationStyle, which made the tab bar overlap
Jus switch back to a default value to fix the issue
The cause of this is that the ancestor viewController is not correctly set.
for instance imagine:
UIViewController * myController = ... // a view controller without a proper ancestor
now:
myController.tabBarController == nil
Therefore:
[myController presentModalViewController:otherController];
Will fail (by showing up under the tab bar). The fix is to add myController to its ancestor via
[parentController addChildViewController:myController];
Now, parentController must be added to another controller in the same way and so forth until the root one is your tabController. This is only available in iOS 5+. If build for iOS 4 or earlier, you will have to work around this by making sure all of your controllers are directly added to either a UINav or UITab controller. If this is not possible, you will have to access the UITabBarController via a global variable.
My app was working great and then client asked to put a login screen on.
I have a TabBarController with 4 tabs and I assign it the window as such in my app delegate.
[self.window addSubview:self.tabBarController.view];
Next, I had to put a login screen (view Controller) so I did it and called it like this
[self.tabBarController presentModalViewController:passwordController animated:NO];
and then dismiss it when the login is correct.
Now, when I put the app in the background each time I get my login screen (YEAH) with the exception of one. One of my tab's calls a navigation controller (well MasterViewController here is actually a view controller) and I call it like this
MasterViewController *masterViewController = [[MasterViewController alloc] init];
//TRYING TO GET IT TO STAY WITH TAB CONTROLLER
UINavigationController *navController = [[[UINavigationController alloc]initWithRootViewController:masterViewController] autorelease];
[self presentModalViewController:navController animated:YES];
and dismiss it when I need to. From there I am doing a bunch of core data stuff and I wanted my tab bar to disappear as I wanted the user to add/edit order in the correct order and not jump around to another place in the app using the tab bar (and then data being out of sync).
When I need to "drill down" to the next level I use
[self.navigationController pushViewController:eventController animated:YES]; and pop when I need to dismiss it.
So my question is this...I want the login screen to be presented on top whenever I return from the background on all screens.
I am sure the problem is the creation of the NavigationViewController not being part of that tabBarController
I did not include more code because it's all core data stuff or view controllers and all works well.
I am sure I am doing something terribly wrong and just don't understand (and I've built the entire app using advice on here so perhaps I followed bad advice).
I solved the problem like this..I created a navigation controller for each of the tabs that needed to "drill down" and had those navigation controllers initialized using the tabbarcontroller. Then in the app delegate when the appfinishedLaunching I called the security controller and it works everywhere. Just wanted to post for those who might be interested.