I have the next question:
In my project I have the next:
UItabbarController
....Some UINAvigationControllers....
*(1) UINavigationController
UIViewController (UItableView) - When select one row it goes to...(by push)
UIViewController (UItableView)
My problem is when i click in the tab bar item, I see the viewController view like last time that i saw this, and no reload to the *(1) first view another time.
Where I need to write sth for each time that i click in a tab bar item i reload the first view of this tab bar item.
Thanks!
If I understand your question correctly, you are trying to return the navigation controller to the root element when it's tab bar item is selected.
To do this, set some object (e.g. your application delegate, but it can be some other object instead) to be the delegate for your UITabBarController. (If you use the application delegate, it will be the delegate for more than one thing, which is fine.) Then, implement the tabBarController:didSelectViewController: method. In that method, tell the selected view controller (which should be a NavigationController) to return to the root view controller.
Something like this. Add this implementation to your AppDelegate.m class:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
[viewController popToRootViewControllerAnimated:NO];
}
In your .xib file, set the delegate for the TabBarController to the the AppDelegate. (If you are programmatically creating the tabBar, you'll have to do it programmatically there.)
As you suspected, trying to do this in viewWillAppear method, or anything other method, of the view controller that live in the navigation controller is not the correct approach. It is a method to perform on the navigation controller, and detected by the delegate of the tab bar.
Try putting your callback code to reload the view in the viewWillAppear or viewDidAppear methods. These are both called every time a view controller displays it's view on the screen.
Also feel free to copy and paste your actual code, it usually makes things easier on our end :)
Related
My UIViewController calls a function on my rootViewController which then called popToRootViewControllerAnimated to return the view to the rootController. This all works - great!
Unfortunately the UINavigationItem (toolbar at the top) seems to display a mashup of both the rootViewController and the UIViewController that has just been removed.
What do I need to do? What have I done wrong?
The navigation bar doesn't remember changes that were made to it, so when you push a new controller, the navigation bar is altered to give the title of the new view controller, but it doesn't store what was there for the previous view controller.
You will need to recreate the items in the toolbar each time you come back to the view controller that has custom items.
You might be able to do this on viewWillAppear instead of viewDidLoad. I can't recall exactly, but you should recreate custom controls on navigation toolbar because it does not get preserved when a new view controller is pushed.
It seems that calling popToRootViewController from the rootViewController messes things up. TO rectify this I called the following from within the calling UIViewController
[self.navigationController popViewControllerAnimated:YES];
I have tabbar based application, I want to start each time tab is pressed to start with first view they are associated with. Problem is it starts with first view when its a start of application but while using application i may navigate deep in to one tab and now what to do if i want to start it again with main view associated with that tab which is pressed?
You can use the tabbar delegates to override this behaviour. The UITabBarControllerDelegate is documented here:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITabBarControllerDelegate_Protocol/Reference/Reference.html
You would want to look at:
tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
Everytime this delegate method is triggered you can trigger the corresponding navigation controller's popToRootViewController:animated method. Normally you'd have your app delegate be the tabbar controller delegate also, but that's up to your implementation.
Alternatively, I could use something like viewWillAppear, only switching tabs doesn't call viewWillAppear - IF I can access selectedItem or selectedIndex reliably from there.
The goal is to re-use a similar table view, with 3 tabs filling the table with differently filtered data.
I tried overriding didSelect and using the app delegate as UITabBarDelegate, but got the error 'Changing the delegate of a tab bar managed by a tab bar controller is not allowed.'
The tab bar controller, rootCt, is in the app delegate and works correctly.
So that's the trick I'm looking for - getting a notification from the root (tab bar) controller when the index has changed. Ideas?
Try implementing an UITabBarController delegate. It has a method similar to the didSelect: method offered by UITabBar delegate:
tabBarController:didSelectViewController:. It will be called after the user has selected another tab.
See: UITabBarControllerDelegate Protocol Reference
tabBarController.tabBar.selectedItem.tag
It will give you the tag of current selected tabbar index
If you are using tabBar den
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
is the delegate method that gets called when tabbar is selected.
happy iCoding...
You can use the delegate method of UITabBarControllerDelegate
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
and in that you have self.selectedIndex will give you the selected index.
I don't usually do this kind of thing (answer my own question). But here goes.
For example, if I click tab 2, then tab 3, then tab 2 again, viewWillAppear for that view is called, but the didSelectViewController method is not - and selectedIndex is not changed!
It appears as if selectedIndex is only updated if a view is loaded, not if the view is already loaded and simply appears.
I did some testing, and unlike selectedIndex, the tab bar's selectedItem is correctly updated (in viewWillAppear for the view in the clicked tab) even if the view is already loaded. By putting f.ex. the tabs' titles in an array, the matching index can be looked up.
So I will omit the didSelectViewController and won't need a UITabBarController, I only need to connect the UITabBar to an IBOutlet and use [myTabBar selectedItem].title to initialize correctly in the re-used view's viewWillAppear.
If someone offers a more generic/useful/simple solution I'll gladly mark that! Will check back in a few days and mark this if not. Just glad I made it work :)
I am using Tab bar + navigation based application and I have 4 tab bars. When I navigate from one view controller to another view controller, the viewWillAppear: method doesn't seem to respond and I am being forced to call it manually by creating the object of the next view controller. So my question is, how do I avoid calling the viewWillAppear: method manually whenever I navigate from one view controller to another? Instead, it should get triggered automatically just like the viewdidLoad: method gets triggered when you navigate from one view controller to other. Please guide me on how could I do that.
Hoping for the best possible Answer
Thanks in Advance
You are correct, viewWillAppear is a little special, it is usually called automatically but in some cases including when you are adding a view controllers view manually (view addSubview:), and also when adding this as a view controller to a UITabBarController or UINavigationCnotroller (of which you have both !) it doesn't get messaged.
This however is only for the root view, as you navigate (maybe with a navigation controller) back and forth, that root view's viewWillAppear will get triggered as some point.
In short, if you need to implement something in viewWillAppear in these cases, you should message it yourself when you know it's going to be presented. You can handle this case in your view controller, check out the following article about the matter:
http://www.touchthatfruit.com/viewwillappear-and-viewdidappear-not-being-ca
Good luck.
You should check UITabBarDelegate then look for the method:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item.
Description: Sent to the delegate when the user selects a tab bar
item.
In some apps that have a tab bar controller, each tab also needs a nav controller before a view can be added:
[[[_mainTabController topViewController] navigationController] pushViewController:renewalScreen animated:YES];
Do you mean 4 tab items on a tab bar, rather than '4 tab bars'? If you have a tab bar with tab items, the viewWillAppear: methods absolutely should be called by the system as the tabs are selected by the user. You could have other issues that are causing the problem.
You didn't forget to call [super viewWillAppear] somewhere?
Try using the viewDidAppear method instead.
I've been reading the Head First iPhone Development book and I understand how to get to a new view from a table but how exactly would I be able to get to a new view or view controller, by just simply pressing a button? Is that even possible?
I mean there are some apps where you click a button, not a table cell and it loads a new view. How exactly is that done? If someone could help out a newbie it would be greatly appreciated!
I think what you're looking for is a modal vew controller. THis presents a modal view like you described on top of everything else. If rootViewController is the view controller that is displaying your current view, and myNewViewController the view controller you want to display modally:
[rootViewController presentModalViewController:myNewViewController animated:YES];
There's plenty of examples of this kind of thing on the net, just search for presentModalViewController
Like bpapa said in the comments, it's hard to be specific without code. However, generally what you want to do is:
Build a navigation controller that contains one original view.
Create a button in your original view using the Interface Builder.
Build a callback method (usually defined with IBAction) that is run when the button is pushed.
In that callback method, create a new view and push it onto the navigation controller the same way you would using a table view cell.
Alternately, if you only want one level of hierarchy, you could use a modal view controller; instead of pushing onto the navigation controller in the last step, just present the modal view controller.
The general answer is that you have an object that manages which view controller loads when.
The most commonly used is the UINavigationController. It is a UIViewController that instead of controlling views, controls other view controllers. It works like a simple stack. You push views you want to display onto the nav's controller stack and when you want them to disappear you pop them off.
A common (though sloppy) way of using a nav is to make it a property of your app delegate. Then anywhere in your app you can references it by:
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
The view controller for the first the user sees is held in the nav's topViewController property. If you want to load a view based on a user action in the topViewController.view, you would have something like this:
- (IBAction) loadNextView:(id) sender{ // Action called by a a UI event such as a button press.
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
UIViewController *nextViewController=...// load from nib, connect with IBOutlet, create programmatically
[nav pushViewController:nextView animated:YES];
}
The first view disappears to be replaced by the next one. To return to the first view, you have a method in the next view controller like so:
- (IBAction) unloadSelf:(id) sender{ // Action called by a a UI event such as a button press.
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
[nav popViewControllerAnimated:YES];
}
... and the nav returns you automatically to the previous view regardless of what that view was.
When you first start out, especially if you use Interface Builder, the structure of the app is largely hidden. Behind the scenes all view controllers and their views exist in a hierarchy of some kind that leads back up to the app delegate. You should train yourself to think in hierarchal terms even if it is not immediately obvious how that hierarchy is constructed.