So I have a UITabBarController, and in one of the tabs I have a UINavigationController. I need to know when the UINavigationController shows and hides. I'm wondering what the best way to do this is.
I can use the UITabBarDelegate to determine when a user clicks on that tab, but often the user is sent to this tab by another means. I can also use viewDidAppear or viewWillHide in the specific view controllers within the UINavigationController, but I want to know when they UINavigationController as a group shows and hides, not any specific view controller within.
Huh. Is there an instance method of the UINavigationController class that looks like this:
[instanceOfNavController isFirstResponder];
You should check the developer documentation for such an instance method.
Related
I have a TabBarController in which I have 5 tabs to access. In one of the tabs I have a Navigation Controller and then the stacks. The navigation controller is being set through IB at this point and the viewcontroller in there is also. Now my concern is that, how can I redraw something based on that particular tabbar as the tableview is not reloading the data since viewWillAppear is not being called when I am in that particular tab.
I am trying to analyze as what is the best way to trigger being in such active tab to trigger such routine. I tried tabbarcontroller didselectviewcontroller delegate pattern in my viewcontroller, and have linked the delegate in my IB from the navigation controller to tabbarcontroller.
However such delegate is not getting triggered when I am in that particular tab item. Any suggestions at this point will be really great?
Thanks
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/
Here's what I have:
A MainWindow.xib file configured with one UIViewController (subclassed to RootViewController). This nib gets loaded at application launch.
RootViewController has two ivars, a custom subclass of UIViewController and a UINavigationController. Both of these are loaded from nibs.
When the application launches both ivars are initialized from their respective nibs, and then the UIViewController.view is added as a subview of RootViewController.view.
Inside UIViewController's view I have a control that triggers an animated swap of UIViewController and UINavigationController. This is where the problem comes in. The swap animates, but the UINavigationController's views are not properly displayed. I get a Navigation Bar with no title, and nothing else.
The UINavigationController nib and underlying functionality have been tested in a stand alone project, but there was no RootViewController.
So, my question is, can I even do this? I've successfully swapped other view controllers like this, but never a UINavigationController. I've seen some documentation that leads me to believe this might be a fools errand, but I haven't convinced myself of that yet.
Solution (Kinda):
I found a solution (workaround? hack?), but it leads to some more questions. I nixed using a Nib for the UINavigationController. Instead, I loaded my UINavigationController's rootViewController from a Nib and then created the UINavigationController programmatically with initWithRootViewController:.
NavRootViewController *navRoot = [[NavRootViewController alloc] initWithNibName:#"NavRootViewController" bundle:nil];
navigationController = [[UINavigationController alloc] initWithRootViewController:navRoot];
[navRoot release];
This works as I expect. Which leads me to the conclusion that the rootViewController property of the UINavigationController wasn't being set properly when I loaded navigationController from a Nib. And the question is, why? Should it?
Also, when you see something like this happening in one case, but not another, it can be beneficial to either create a subclass and make your nib point at that subclass, or if you already have a subclass use that.
In the subclass, override all the various init:, initWithNibName:bundle:, viewDidLoad:, viewWillAppear:, viewDidAppear: and any other appropriate methods, and in those override, just NSLog("") something about which method it is (with param values perhaps) and call the super implementation.
This will give you an observable "track" of which methods are called in which order, and you can set a breakpoint to see where that call comes from.
This will give you enough information to find missing method calls, and then you can pursue the correct problem either here, or through filing a radar or ...
In some cases, viewDidLoad and viewDidAppear or awakeFromNib may need to be called each time you add the UINavigationController back into the stack of UIViewControllers. It seems that when the typical code executes out of your AppDelegate, that the Window, or something behind the scenes is doing something special for UINavigationController that presentModalViewController doesn't do.
I think you may have missed a conceptual point.
A UINavigationController controls view controllers instead of views. It controls when and where view controllers themselves are loaded. The views themselves are loaded only as a side effect of the pushing and popping of their respective controllers.
Therefore, putting a navigation controller inside of a view controller seldom makes much sense.
If I understand what you are trying to do correctly, you should have the RootController actually set as the rootController property of the UINavigationController (yes the nomenclature is extremely confusing.) Then when your swap event occurs, you should have the navigation controller push the next view. The RootController view will disappear to replaced by the other. then you can repeat the process for an arbitrary number of view controllers.
Only in the case of a tabbar would you want a navigation controller to be a property of a view controller. Even then it should be at the top the tab's hierarchy.
I am using a tab bar (UITabBarController) on my app and I wish to customize the appearance of the table that appears when you click the more button.
My app customized with a background image on every page. But image is not displaying when i click more button.
Any ideas?
If you're actually using UINavigationController embedded within a UITabBarController then the more item is a UINavigationController which exists as a property of your UITabBarController with the name moreNavigationController. You can manipulate it in methods of your UITabBarController just as you can any other UINavigationController.
HTH, Pedro :)
It sounds like you have a UINavigationController as the main VC of your app, and a UITabBarController as one of the VC's on its stack.
I believe Apple actively discourages people from doing this in their apps, and so do I. It is never done in the iOS itself, and I have never seen it in any third-party apps either, so users will probably be confused.
I think you should embed the UINavigationController inside the UITabBarController instead of the other way around, or you could just choose to use another way of showing what you want to show.
see UITabBarController's 'More' navigation controller disappears under UINavigationController
Fundamentally, what I want to do is within, for example, ViewControllerA display ViewControllerB and ViewControllerC. How would I do that?
Thanks in advance.
You don't display view controllers, you display views. Having said that, you can do something like this:
UIViewController *a = ...;
UIViewController *b = ...;
[a.view addSubview:b.view];
Now, having said that, you shouldn't do it. Tons of stuff does not behave properly, because there are tons of undocumented interactions between UIView, UIWindow, and UIViewController. There is nothing in the documentation that says it won't work, but random things stop behaving properly (viewWillAppear: on the interior view's VC doesn't get called, etc).
If you need this functionality, you should file a bug with Apple.
The default template for a navigation view controller should do what you want assuming you want two different screens (not two different sections on the same screen). Whenever you want to change the view from the current one to another, just tell the navigation controller to push it on the stack:
[self.navigationController pushViewController:viewBoards animated:YES];
The default navigation view controller gives you a root view controller with a navigation view controller in it. It also gives you one view controller called MainWindow. Just add as many copies of MainWindow as you need to get your functionality.