自适应弹出窗口上的关闭按钮

Nic*_*ick 15 objective-c uikit ios uistoryboard

在故事板中,我有一个带有按钮的根视图控制器,该按钮触发"Present as Popover"segue到包含UITableViewController的UINavigationController.我希望导航控制器能够出现在iPhone和iPad上.

在iPad上,这在popover中非常有用.

在iPhone上,我得到了模态演示,所以现在我需要一个额外的条形按钮项来消除模态视图.从观看WWDC视频开始,我在根视图控制器中尝试了以下内容:

- (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;
}
Run Code Online (Sandbox Code Playgroud)

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

Tra*_* M. 14

对于那些想要快速剪切和粘贴的人来说,这是Swift版本的Nick的正确答案.

注意:这是在iPad上创建一个弹出窗口,但在iPhone上有一个关闭按钮的模态表.

在Xcode 6.3 storyboard中,你连接一个视图控制器并将segue指定为"作为弹出窗口存在"

下面的代码应该放在视图控制器中,它分隔到弹出框,而不是弹出框本身:

首先设置popover委托:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "myPopoverSegueName" {
        segue.destination.popoverPresentationController?.delegate = self
        return
    }
}
Run Code Online (Sandbox Code Playgroud)

然后添加委托扩展并动态创建导航控制器/关闭按钮:

extension myViewController: UIPopoverPresentationControllerDelegate {

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

    @objc private func dismissPopover() {
        dismiss(animated: true, completion: nil)
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这个有效!! 谢谢!在另一个注释中,如果不想手动处理单词Done的本地化,可以使用此代码:)让btnDone = UIBarButtonItem(barButtonSystemItem:UIBarButtonSystemItem.Done,target:self,action:"dismiss")if if (4认同)

Nic*_*ick 12

好的,我已经设法让它工作.我认为我的问题是该popoverPresentationController属性遍历视图控制器层次结构,直到它找到一个带有a的视图控制器popoverPresentationController,即如果我在弹出窗口内的导航控制器内有一个视图控制器,则视图控制器popoverPresentationController将转到导航控制器并使用它的属性.为此,视图控制器必须是导航控制器的子级.在所有我试图使用点popoverPresentationController,这种情况并非如此,例如init,viewDidLoad,viewWillAppear.出于某种原因,willMoveToParentViewController即使被调用,也didMove不会被调用.所以我不知道如何popoverPresentationController在调用ppc委托方法之前在nav控制器中引用vc.

但是,您可以在呈现视图控制器中引用它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;
}
Run Code Online (Sandbox Code Playgroud)