I created a simple project to demonstrate this strange behavior. I created all of this in the interface builder without touching the code so that it's easy for you to reproduce.
The start page is embedded in the navigation controller containing only one button, and when clicking on it, the screen will be directed to the tab views (with navigation bar on the top).
There are 2 strange things happening when running the program.
1) The tab item2's table view is underneath the navigation bar where as the item1's is displayed correctly.
vs.
As you can see, although the two table view is placed in the exact same position, when the program runs, the second one even hides the search bar because of the incorrect alignment.
2) When clicking on the search bar in tab item1, the navigation bar is not hidden as the default behavior (where the nav bar hides and the search bar shows instead).
Since the nav bar is semi translucent, I can see the 'Cancel' button underneath the nav bar.(Any one with a good eye can see the blue tint at the upper right corner of the screen shot). It means the search bar goes to the correct location but the nav bar just doesn't go away.
Also, note that the table view is not shifted up with the search bar(again, default behavior) when the search bar is active.
PS: I am using XCode 6. Also I tried adding constraints to the tableviewcontrollers, but no dice.
Any ideas on this? Thanks in advance.
As logixologist suggested, you can put a navigation controller for each tab as the first controller of the tab. If you don't want to do that, you can add the following code in viewDidLoad of second item view controller.
CGFloat shiftDist = CGRectGetHeight(self.navigationController.navigationBar.frame) + CGRectGetHeight([UIApplication sharedApplication].statusBarFrame);
self.tableView.contentInset = UIEdgeInsetsMake(shiftDist,0, 0, 0.0f);
self.tableView.contentOffset = CGPointMake(0, -shiftDist);
After that, there is problem for rotation. You'll notice if you rotate to landscape, the search bar doesn't stick under the navigation bar. Here is how to fix it.
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
CGFloat heightBeforeRotation = CGRectGetHeight(self.navigationController.navigationBar.frame) + CGRectGetHeight([UIApplication sharedApplication].statusBarFrame);
CGFloat offsetY = self.tableView.contentOffset.y;
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
CGFloat heightAfterRotation = CGRectGetHeight(self.navigationController.navigationBar.frame) + CGRectGetHeight([UIApplication sharedApplication].statusBarFrame);
self.tableView.contentInset = UIEdgeInsetsMake(heightAfterRotation,0, 0, 0.0f);
self.tableView.contentOffset = CGPointMake(0, heightBeforeRotation + offsetY - heightAfterRotation);
}];
}
The issue is how the Tab Bar Controller is presented. Tab Bar Controllers are special and generally should be the initial view controller in your storyboard.
If the Tab Bar Controller is not the initial view controller then it should be presented modally. In my test app I changed the segue to "Present Modally".
Then added a Navigation Controller for each Tab bar Table View Controller with a done button that dismissed the modal Tab Bar Controller.
- (IBAction)DoneButton:(id)sender {
[self.parentViewController dismissViewControllerAnimated:YES completion:nil];
}
Per Apple's Documentation "View controller Catalog for iOS"
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/CombiningViewControllers.html
Adding a Navigation Controller to a Tab Bar Interface
An app that uses a tab bar controller can also use navigation
controllers in one or more tabs. When combining these two types of
view controller in the same user interface, the tab bar controller
always acts as the wrapper for the navigation controllers.
The most common way to use a tab bar controller is to embed its view
in your app’s main window. The following sections show you how to
configure your app’s main window to include a tab bar controller and
one or more navigation controllers. There are examples for doing this
both programmatically and using Interface Builder.
Tab bar views do not support translucency and tab bar controllers
never display content underneath their associated tab bar. Therefore,
if your navigation interface is embedded in a tab of a tab bar
controller, your content may underlap the navigation bar if you adopt
a full-screen layout as described in Adopting a Full-Screen Layout for
Navigation Views, but it does not underlap the tab bar.
When embedding navigation controllers in a tab bar interface, you
should embed only instances of the UINavigationController class, and
not system view controllers that are subclasses of the
UINavigationController class. Although the system provides custom
navigation controllers for selecting contacts, picking images, and
implementing other behaviors, these view controllers are generally
designed to be presented modally. For information about how to use a
specific view controller, see the reference documentation for that
class.
Displaying a Tab Bar Controller Modally
It is possible (although uncommon) to present a tab bar controller modally in your app. Tab bar interfaces are normally installed in
your app’s main window and updated only as needed. However, you could
present a tab bar controller modally if the design of your interface
seems to warrant it. For example, to toggle from your app’s primary
operational mode to a completely different mode that uses a tab bar
interface, you could present the secondary tab bar controller modally
using a crossfade transition.
When presenting a tab bar controller modally, you always pass the tab
bar controller object as the first parameter to the
presentModalViewController:animated: method. The tab bar controller
must already be configured before you present it. Therefore, you must
create the root view controllers, configure them, and add them to the
tab bar controller just as if you were installing the tab bar
interface in your main window.
As with all other modally presented view controllers, the parent view
controller is responsible for dismissing its modally presented child
view controller in response to an appropriate user action. When
dismissing a tab bar controller though, remember that doing so removes
not only the tab bar controller object but also the view controllers
associated with each tab. The view controllers that are not visible
are simply removed, but the view controller displayed in the currently
visible tab also receives the usual viewWillDisappear: message.
For information on how to present view controllers (including
navigation controllers) modally, see Presenting View Controllers from
Other View Controllers in View Controller Programming Guide for iOS.
For information on how to configure a tab bar controller for use in
your app, see Tab Bar Controllers.
In my iOS app I have the following :
Navigation Controller
Some other controller
UITabBarController
UITableView
UISearchBar + UISearchDisplayController
The behaviour I would expect to have is the search bar would move to the navigation bar when focused.
Instead currently it stays where it is : at the top of the table view.
I tried the same view without the TabBarController and the search works as expected : it moves to the navigation bar on focus.
Any idea how to fix this ?
I would like to have my search bar launched from a UIBarButton that I have added to my navigation bar from the storyboard. I have also added the Search Bar and Search Display Controller to the document outline in my view controller from the storyboard.
If I implement the code below in my viewDidLoad method the search bar will automatically appear in my navigation bar self.searchDisplayController.displaysSearchBarInNavigationBar = YES;
However, when I try and implement this in from a button click from my navigation bar nothing happens.
(IBAction)serachBarButton:(id)sender
{
self.searchDisplayController.displaysSearchBarInNavigationBar = YES;
}
The IBAction is properly hooked up to the view controller in the storyboard. Any code examples of how to launch the search bar from my navigation button click would be greatly appreciated.
I have the following constellation:
Main View (Custom UIViewController, no navigationcontroller or navigation bar), containing a button which segues modally to a second Table view controller, which is embedded in a Navigation Controller:
MainView -> Navigation Controller -> TableView
On the MainView the status bar is Black (no changes with iOS 6 - even when Status Bar is set to Default)
On the TableViewController the status bar should have Default Style (grey in iOS 5, Blue Tinted due to navigation bar in iOS 6).
In iOS 5 this was easy by the following lines of code in TableViewController:
if ([[UIApplication sharedApplication] respondsToSelector:#selector(setStatusBarStyle:)]) {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
}
Running this under iOS 6 noting happens. How can I do this? I tried all possible Status Bar settings under project summary and in the plist (like described here: https://stackoverflow.com/a/12468689/1685971)
Also, in Storyboard everything looks fine. Running the app in simulator or on the device it looks different:
try this "hack":
You have to add a navigation bar to your first view controller. Then you have two possibilities.
1) Set the alpha value of the navigation bar to 0
or
2) Set the y-position of the bar to -43px (look here: http://moduscreate.com/tinting-your-status-bar-in-ios6-and-phonegap/)
EDIT:
To get the right colors you have to set the tintColor of the invisible UINavigationBar. So by default set it black. In your button action you have to set the tintColor to your navigationController.navigationBar.tintColor. At the action of your close button you need to set it back to [UIColor blackColor].
The first view controller must have a navigation controller/bar for the feature to work. The status bar does not change color throughout your app (in iOS6) but adapts to the navigationbar color of you starting view. If your starting view does not contain a navigationbar, the status bar does not adapt color.! (See http://i.stack.imgur.com/n9ubK.png)
You don't have to set the style for the navigation bar to your tableviewcontroller.
Try this approach.
1. Add navigation controller to the main view.
2. Set its property hidden to yes.
3. When you display tableviewcontroller, set the navigation bar property hidden to No
Navigation Controller -> bar hidden= yes ->
MainView -> bar hidden=no -> TableView
In my tabbarcontroller application having four bars, each tabbar having navigationcontroller inside viewcontroller. How should i hide for particular tabbar for particular tab in landscape orientation?.
To hide the TabBar when you push a new viewController to the navigation stack, simply add this code to the init method of that viewController:
self.hidesBottomBarWhenPushed = YES;