带有 UITabBarController 的 ABPeoplePickerNavigationController 在 iOS8 中未正确显示

ABPeoplePickerNavigationController with UITabBarController is not showing correctly in iOS8

我有一个应用程序,其中 UITabBarController 作为具有两个控制器的 rootViewController。一个是空控制器,第二个是从 ABPeoplePickerNavigationController 扩展的 Picker 控制器。问题是视图在选项卡栏后面,并且由于该视图从底部被切断。我刚刚在屏幕截图中突出显示了该区域:

非常感谢任何帮助。

官方ABPeoplePickerNavigationController不支持subclassing:link here

Subclassing Notes
The ABPeoplePickerNavigationController class does not support subclassing.

但是,问题在于您的 ABPeoplePickerNavigationController subclass 的视图在选项卡栏下扩展。 例如,您可以通过这种方式在运行时更改它的大小

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    CGRect rect = self.view.bounds;
    rect.size.height = rect.size.height - 40;
    self.view.frame = rect;
}

请注意,40 只是一个示例,您应该计算标签栏控制器的高度,因为它可能会因其他屏幕尺寸和旋转而改变。

或者,更好的是,您可以搜索底层 UITableView 实例并设置 contentInset 属性。

编辑 这似乎与状态栏有关,因为 ABPeoplePickerNavigationController 无法扩展状态栏下的导航栏,如果您更改它的框架

然而,在这两种情况下,您的应用程序可能会被拒绝,因为您正在提交 class 明确禁止它的 class。

更好的 "legal" 添加它的方法是使用容器视图控制器

看看This Example

创建一个新的视图控制器,添加一个容器视图,然后按此方式添加ABPeoplePickerNavigationController

-(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];

}

即使这样 ABPeoplePickerNavigationController 状态栏也有问题(它不能在其下正确延伸),所以我将容器视图限制在顶部布局指南并更改了主视图的颜色ContainerViewController 以适应导航栏的颜色

viewWillAppear

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.topViewController.extendedLayoutIncludesOpaqueBars = YES;
}

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);
}

聚会有点晚了,但这是我对问题的回答,或者至少是一些额外的输入,以便您制定出完整的解决方案。

对我来说问题似乎是因为 UIPeoplePickerNavigationController 不是可子类化的或者至少 Apple 不推荐这样子类化,所以您不能随心所欲地完全使用它。我的意思是 UIPeoplePickerNavigationController 旨在用作模态视图,它应该在 iOS 上全屏显示并位于所有其他视图控制器之上。您不应尝试将其用作导航控制器堆栈上的推送视图控制器。

所以我的建议很直接。您应该简单地使用 UITabBarController 作为 presentViewController:animated:completion: 方法的接收者。这将负责在选项卡栏顶部呈现模式。

您可以通过当前视图控制器的 tabBarController 属性 访问 UITabBarController

ABPeoplePickerNavigationController *peoplePickerController = [ABPeoplePickerNavigationController new];
[peoplePickerController setPeoplePickerDelegate:self];
[self.tabBarController presentViewController:peoplePickerController animated:YES completion:^{}]

注意:我是凭记忆写的,所以可能有一些方法命名错误。