I have a tabBar controller. Tapping the active tab, by default, calls popToRootViewController on that tab's navigation controller. That is what I want, but I also need to do some customization when this happens. The view controller in question has a nav controller, but is not a subclass of UINavigationController. How can I listen for when popToRootViewController occurs and take some action?
You can use UINavigationControllerDelegate's method:
– navigationController:didShowViewController:animated:
and check if the shown controller is the controller you want.
Hopes this helps
(I remember using this in iOS 2.x and it was a little bit buggy, I wonder if is ok now. It should be since it's 4 already)
You can put you code inside the method – tabBarController:didSelectViewController: of the UITabBarController delegate, or maybe inside the UIViewController's - viewWillAppear:animated: method.
Note:
If you have added your Tabbarcontroller in the navigation stack,
-(void)viewWillAppear:(BOOL)animated
would not be called in iOS 4.2 or below, I wasted so many days to figure out this.
Related
I have app with 3 UIViewContoller
UIViewContollerA
UIViewContollerB
UIViewContollerC
UIViewContollerA open UIViewContollerB with presentModalViewController
UIViewContollerB open UIViewContollerC with presentModalViewController
And i want to have the possible that in one click on button in UIViewContollerC to dismiss all The UIViewController.
I try to call dismissModalViewControllerAnimated twice but it won't work, there is any other option to do it?
it's possible?
I would take a look at unwind segues. They allow you to unwind to any previous segue. The answers in this question are very helpful in describing how to use them: What are Unwind segues for and how do you use them?
Also as mentioned by Michael, modals weren't designed to be placed one on top of the other. I've found they work great for forms, but not much else. I would suggest that you use a UINavigation Controller as well. This will allow you to easily navigate back to the previous controller. Then you could also add a button for an unwind segue back to the initial view controller that you want.
You probably need some sort of chaining set of calls back up the modal stack to do this.
However, given you have a stack of view controllers, a UINavigationController might be a simpler solution to both presenting these view controllers in the first place and dismissing them down in one go.
Of course calling dismissModalViewControllerAnimated won't work, it's intended to be called on different view controllers. From the docs:
Dismisses the view controller that was presented by the receiver
So you'll need to set up delegation between the controllers in order to pass a request to dismiss the controller backwards to the initial controller.
Keep in mind that:
There's probably a better way of doing whatever it is you're trying to do. Modal controllers weren't intended to be presented on top of each other.
You're using deprecated methods. Use
presentViewController and dismissViewController instead
you would pass a reference of UIViewContollerB in UIViewContollerC, like this
#property(nonatomic, assign) UIViewContollerB *refB;
and call dismissModalViewControllerAnimated in UIViewContollerC to dismiss it, and fire dismiss action of UIViewContollerB in viewWillDisappear
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.refB dismissModalViewControllerAnimated:YES]
}
What you could try is to use dismissModalViewControllerAnimated with animated:NO. On the top most one and animated:YES on the controller below.
Or perhaps it workd, if you just call dismiss on the rootController?
I am presenting modal using the following code :
AddName *add = [[AddName alloc] initWithNibName:#"AddName" bundle:nil]
add.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalView:add animated:YES];
And After my work I use following code to go back on my main view.
[self dismissModalViewControllerAnimated:YES];
So it use to call -viewWillAppear by default.
My problem is that,
It was working fine with iOS4.3.
But Its not working with iOS5.
What should I do ? Or Is that any bug in iOS5?
-viewWillAppear is only guaranteed to be called in places where the -viewWillDisappear has also been called. For most modal windows on the iPad, this is not the case, since they don't obscure the entire page.
The solution to your problem will depend on what you need the -viewWillAppear for, but in general, you're likely to need to make a call directly from the same place that you dismiss the modal view controller.
One common mechanism for this, especially in cases where you might use that same modal view somewhere else, is to give the modal view controller a delegate which is called when the view is about to disappear. This will give you a chance to take the responses from the modal window, or even just force a data reload in the delegate view.
Hope this helps.
iOS 5 definitely changed their calls to viewWillAppear and viewWillDisappear. For instance, subviews (View Controller's views as subviews to be exact) in a UIScrollView, viewWillDisappear will get called when you push another view controller onto the stack. However, when the view controller is popped, viewWillAppear does not get called. These methods were never called in iOS 4 on UIScrollView subviews.
This is strange behavior to me. Couple that with the fact that regardless of what should happen, if you could rely on it happening in iOS 4, it should not be working differently in iOS 5. Most of the time, I have no idea in which particular instance each one is called, I usually trial and error it as I'm in the zone coding. If it works the way I like, I move on. Then iOS 5 comes in and throws a wrecking ball into everything.
I have also experienced when a UINavigationController's view is a subview, and a ViewController is pushed on the navigation controller stack, viewWillAppear never gets called in iOS 4, but does get called in iOS 5. Go figure.
I had the same problem.
I found that viewWillAppear isn't get called after dismissing modal but viewDidAppear is. So just try viewDidAppear instead.
So my app's core is a tab bar. In each of 3 tabs is a UINavigationController subclass. Each one has a different type of table in it, which when a row is tapped, a detail is shown etc.
I currently have a 3 separate subclasses of UINavigationController, one for each tab. Then when a new tab is pressed, the table's controller is pushed.
I just read that you're not supposed to subclass UINavigationController. I'm not overriding any of UINavigation Controller's functionality, but I am overriding it's UIViewController functionality in viewDidLoad. Honestly that's just about it. It seems pretty silly, but Im unclear on how to get the Navigation Controller functionality without subclassing the way I have.
So how am i supposed to have a UINavigationController that I don't subclass? What is the approach that you're supposed to take to switch out the views when a tab is selected?
I'm pretty much a noob. Will Apple reject my app for subcalssing UINavigationController if im only overriding viewdidload?
I've heard folks say not to subclass UINavigationController, and instead 'present it modally.' I have used modal presentation a little bit, but I honestly dont' quite get how it would apply...
Thanks for your help!
What are you doing in viewDidLoad? What about do it in root view controller, not in navigation controller?
P.S. I think Apple will not reject your app for subclassing UINavigationController.
You should use categories to add extra functionality like that. It would look something like this:
#implementation UINavigationController (CustomViewDidLoad)
- (void)viewDidLoad
{
//code goes here
}
#end
You can add this to the bottom of the file that initializes the navigationcontroller
More info about categories (at the bottom): http://cocoadevcentral.com/d/learn_objectivec/
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 have to use a UITabBarController inside UINavigationController. Everything seems to be right, but if i log the dealloc calls of the tabs some strange thing happens.
If I don't touch eanything just the back button, all dealloc of each tabs are called.
If I switch to any other tab and than I tap the back button the dealloc of the first tab won't be called but the others will.
What can be wrong whit that?
Take a look at this SO question. Basically, a tab bar controller inside a nav controller isn't officially supported, but you can mimic the behavior by using a tab bar without a UITabBarController.