Determine how a view controller is being presented

828 views Asked by At

I am presenting a view controller modally with its UIModalPresentationStyle set to the adaptive style UIModalPresentationPopover. This style when in a horizontally compact environment (iPhone portrait) will appear over the full screen. When in a horizontally regular and vertically compact environment (iPhone 6 Plus landscape) it will appear in a form sheet. And when in a regular regular environment (iPad) it will appear as a popover. This is the desired behavior.

I need to programmatically determine how that controller will actually be displayed - form sheet, over full screen, or popover. How can I determine that from within the view controller that is being presented?

The reason is I need to add a Done button only in the case it is not within a popover. (Or hide it in the case it is in a popover.)

Creating the view controller:

let viewController = ...
viewController.modalPresentationStyle = .Popover

let popoverController = viewController.popoverPresentationController
popoverController?.barButtonItem = settingsButton

presentViewController(viewController, animated: true, completion: nil)

Inside the viewController:

- (void)viewDidLoad {
    [super viewDidLoad];

    //self.modalPresentationStyle is Popover even in the case where it's presented over the full screen
    //self.popoverPresentationController is not nil even when presented full screen
}
1

There are 1 answers

0
James On

I am not Swift fluent, so I'll try an answer without too much bad Swift code.

I believe you just want to make your controller a UIPopoverPresentationControllerDelegate then implement:

optional func adaptivePresentationStyleForPresentationController(_ controller:
     UIPresentationController,
       traitCollection traitCollection: UITraitCollection) -> UIModalPresentationStyle

In that function you can return the presentation style you want based on the traitCollection passed in to the function. (available after iOS 8.3) This gives YOU control over the display choice made based on the traitCollection.

Another part of the delegate protocol gives you a place to wrap the popover in a navigation controller.

   optional func presentationController(_ controller: UIPresentationController,
viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController?

In Objc I do the following:

UINavigationController *navController = [[UINavigationController alloc] 
    initWithRootViewController:controller.presentedViewController];
return navController;

Then there are several ways you could get the Done button to show up. One would be check if you are inside a navigation controller and inserting a Done button in the nav bar. FWIW, I have been using a storyboard with the Navigation Item and Right Bar button added to the popover view controller. They don't show up unless I add the navigation controller.

Remember to assign your controller as the delegate:

popoverController?.barButtonItem = settingsButton
popoverController?.delegate = self