closures自适应popup窗口button

在故事板中,我有一个带有button的根视图控制器,触发一个包含UITableViewController的UINavigationController的“呈现为popup窗口”。 我希望导航控制器在iPhone和iPad上均可使用。

在iPad上,这个function非常出色。

在iPhone上,我得到了模态演示文稿,所以现在我需要一个额外的栏button项目来消除模态视图。 从观看WWDCvideo,我已经在根视图控制器中尝试了以下内容:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { UIViewController *vc = segue.destinationViewController; vc.popoverPresentationController.delegate = self; } - (void)dismissPopover { [self dismissViewControllerAnimated:YES completion:nil]; } - (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style { UINavigationController *nvc = (UINavigationController *)controller.presentedViewController; UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(dismissPopover)]; nvc.topViewController.navigationItem.leftBarButtonItem = bbi; return nvc; } 

我知道-presentationController:viewControllerForAdaptivePresentationStyle:方法应该只在UI自适应,即模态时被调用,但是它根本不会被调用,即使在iPhone上作为模式运行时也是如此。

好吧,我设法让它工作。 我认为我的问题是, popoverPresentationController属性遍历视图控制器popoverPresentationController ,直到它find一个视图控制器与popoverPresentationController ,即如果我有一个视图控制器内的导航控制器内popup窗口视图控制器popoverPresentationController将去导航控制器和使用它的属性。 为了这个工作,视图控制器必须是导航控制器的孩子。 在所有我试图使用popoverPresentationController ,情况并非如此,例如initviewDidLoadviewWillAppear 。 出于某种原因, willMoveToParentViewController不被调用,即使didMove不被调用。 所以我不知道如何在调用ppc委托方法之前在nav控制器内的vc中引用popoverPresentationController

但是 ,您可以在prepareForSegue中的呈现视图控制器中引用它,但是您确实需要明确告诉它要使用的演示样式。 这是我的代码,当放置在呈现视图控制器时工作:

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { UIViewController *dest = segue.destinationViewController; dest.popoverPresentationController.delegate = self; } - (void)dismiss { [self dismissViewControllerAnimated:YES completion:nil]; } - (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller { return UIModalPresentationFullScreen; // required, otherwise delegate method below is never called. } - (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style { // If you don't want a nav controller when it's a popover, don't use one in the storyboard and instead return a nav controller here UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(dismiss)]; UINavigationController *nc = (UINavigationController *)controller.presentedViewController; nc.topViewController.navigationItem.leftBarButtonItem = bbi; return controller.presentedViewController; } 

对于想要快速剪切和粘贴的人,Nick的正确答案是Swift版本。

注意:这是为了在iPad上创build一个popup窗口,但是在iPhone上有一个closuresbutton的模式表单。

在Xcode 6.3的故事板中,你连接了一个视图控制器,并将这个segue指定为“Present as Popover”

下面的代码应该放在视图控制器中,而不是放在弹窗中:

首先你设置popover代表:

 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if (segue.identifier == "myPopoverSegueName") { let vc = segue.destinationViewController vc.popoverPresentationController?.delegate = self return } } 

然后添加委托扩展,并即时创build导航控制器/closuresbutton:

 extension myViewController: UIPopoverPresentationControllerDelegate { func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? { let btnDone = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismiss") let nav = UINavigationController(rootViewController: controller.presentedViewController) nav.topViewController.navigationItem.leftBarButtonItem = btnDone return nav } } 

然后你添加你的解雇function,你应该很好去:

 func dismiss() { self.dismissViewControllerAnimated(true, completion: nil) } 

我发现接受的答案在紧凑模式(例如iPhone)下不能正确显示“完成”button,但在常规模式(例如iPad)中保持为popup状态。

下面的代码是做这个工作的最低限度 – 把它们放在呈现视图控制器类中。

 -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { UIViewController *dest = segue.destinationViewController; dest.popoverPresentationController.delegate = self; } - (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style { UIViewController* presentedViewController = controller.presentedViewController; if ([controller isKindOfClass:[UIPopoverPresentationController class]] && style == UIModalPresentationFullScreen) { UINavigationController* navCtrl = [[UINavigationController alloc] initWithRootViewController:presentedViewController]; UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(dismiss:)]; presentedViewController.navigationItem.rightBarButtonItem = bbi; return navCtrl; } return presentedViewController; } -(IBAction)dismiss:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } 

注意与接受的答案的三个区别:

  • 我们不需要重写adaptivePresentationStyleForPresentationController:
  • 我们检查演示控制器是否是popup窗口,而是请求全屏模式。
  • 我们返回一个新的导航控制器实例,而不是(错误地)将所呈现的视图控制器转换为导航控制器。