ABPeoplePickerNavigationController with UITabBarController does not display correctly in iOS8
I have an application where UITabBarController is as rootViewController with two controllers. One is an empty controller and the second is a Picker controller coming from ABPeoplePickerNavigationController. The problem is that the view goes behind the tab bar, and because of this, the view is disabled from the bottom. I just highlighted the area in the screenshot:
Any help would be much appreciated.
source to share
ABPeoplePickerNavigationController
Doesn't officially support subclasses: link here
Subclassing Notes
The ABPeoplePickerNavigationController class does not support subclassing.
However, the problem is that the view of your subclass ABPeoplePickerNavigationController extends below the tab bar. You can, for example, resize it at runtime this way.
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect rect = self.view.bounds;
rect.size.height = rect.size.height - 40;
self.view.frame = rect;
}
Note that 40 is just an example, you have to calculate the height of your tab bar controller because it might change for other screen sizes and rotations.
Or, better, you can find the underlying UITableView instance and set the property contentInset
.
EDIT
This looks like status bar issues as ABPeoplePickerNavigationController
it cannot expand the navigation bar in the status bar if you change its frame
In both cases, however, your application is likely to be rejected because you subclass a class that explicitly disallows it.
The best and "legal" way to add it is using the container view controller
Take a look This example
Create a new view controller, add the container view, then add ABPeoplePickerNavigationController
like this:
-(void)viewDidLoad
{
[super viewDidLoad];
// create the ABPeoplePickerNavigationController instance
ABPeoplePickerNavigationController *controller = [[ABPeoplePickerNavigationController alloc] init];
// add a new child view controller to self
[self addChildViewController:controller];
// alert the child that it has been added to the father
[controller didMoveToParentViewController:self];
// update the child view frame to fit into the containerView
controller.view.frame = self.containerView.bounds;
// translate autoresizing mask into constraints, this is not needed but I usually do because is more pratical
[controller.view setTranslatesAutoresizingMaskIntoConstraints:YES];
// add the `ABPeoplePickerNavigationController` view to the container
[self.containerView addSubview:controller.view];
}
Even so, ABPeoplePickerNavigationController
has problems with the status bar (it doesn't go right underneath it), so I limited the container view in the Top Layout Guide and changed the color of the main view ContainerViewController
to match the color of the navigation bar
source to share
In viewWillAppear
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.topViewController.extendedLayoutIncludesOpaqueBars = YES;
}
In viewDidAppear
- (void)viewDidAppear:(BOOL)animated
{
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
CGRect tabBarFrame = self.tabBarController.tabBar.frame;
self.view.frame = CGRectMake(0, statusBarFrame.size.height, self.view.frame.size.width, CGRectGetMinY(tabBarFrame) - statusBarFrame.size.height);
}
source to share
A bit late to the party, but here is my answer to the problem, or at least some additional input for you to work out a complete solution.
The problem for me seems to be that since UIPeoplePickerNavigationController
it is not a subclass, or at least not recommended by Apple, you cannot use it completely the way you like. I mean, this is UIPeoplePickerNavigationController
intended to be used as a modal view that needs to be presented full screen on iOS and on top of all other controllers. You shouldn't try to use it as a push view controller on the navigation controller stack.
So my proposal is pretty straight forward. You just have to use yours UITabBarController
as the method receiver presentViewController:animated:completion:
. This will take care of presenting the modality on top of the tab bar.
You can access UITabBarController
via a property of tabBarController
your current controller:
ABPeoplePickerNavigationController *peoplePickerController = [ABPeoplePickerNavigationController new];
[peoplePickerController setPeoplePickerDelegate:self];
[self.tabBarController presentViewController:peoplePickerController animated:YES completion:^{}]
Note. I am writing this from memory, so there might be some errors in the method names.
source to share