Search code examples
iosobjective-cswiftpopover

How to use dismiss an iPhone popover in a Storyboard


I would like to use the solution provided by Travis M. to this question: How to use dismiss an iPhone popover in an Adaptive Storyboard

However, I would need the below be translated to objective c.

Anyone could help out?


If what you want is a popover on your iPad but a modal sheet with a close button on your iPhone then you can do it without creating an extra navigation controller in storyboard for the popover.

In Xcode 6.3 storyboard, you simply hook up a view controller and designate the segue as a "Present as Popover"

The code below should go in the view controller that segues to the popover, not in the popover itself:

First you set up the popover delegate:

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

Then you add the delegate extension (below your view controller's code) and create the navigation controller / close button on the fly:

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

Then you add the delegate extension (below your view controller's code) and create the navigation controller / close button on the fly:

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

Then you add your dismiss function and you should be good to go:

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

Solution

  • It's not that different from objective-c. You could probably figure out what's going on just by looking at it. It's just setting up prepare for segue and implementing part of a protocol.

    myViewController needs to declare itself as conforming to UIAdaptivePresentationControllerDelegate. Then this is the code.

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
            if ([[segue identifier] isEqualToString:@"myPopoverSegueName"]) {
                UIViewController *viewController = segue.destinationViewController;
                viewController.popoverPresentationController.delegate = self
            }
        }
    
    - (UIViewController *)presentationController:(UIPresentationController *)controller
      viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style
    {
                UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismiss)];
                UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller.presentedViewController];
               navController.topViewController.navigationItem.leftBarButtonItem = doneButton;
    
    }
    
    -(void) dismiss
    {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    

    You don't need to use an extension or category. Not going to vouch for whether this does what Travis M. says it does.