Now that XCode 6 and iOS 8 enable size classes, there is only one storyboard for all devices. Fine. But in the same time, Apple recommends to avoid using bar button items to dismiss a popover. Now, how can I do to have a UIBarButtonItem when presenting on an iPhone, and not when presented inside a popover on an iPad ?
Precision : I know how to disable a UIBarButtonItem based on the fact that the device is an iPad. I'm looking for a way to specifically detect that a popover is displayed.
EDIT: this code works, but I'd like something less device-dependent:
if traitCollection.userInterfaceIdiom == .Pad {
navigationItem.rightBarButtonItem = nil
}
EDIT: I created a small Github project to make my question clear : Github - Test Popover
Thanks!
I finally found how to solve that issue :
PrepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
// switch on the segue.identifier
// ....
case .DisplayPreferences:
print("Segue to Preferences")
if let popoverPresentationController = segue.destinationViewController.popoverPresentationController {
popoverPresentationController.delegate = self
}
// ....
}
UIPopoverPresentationControllerDelegate:
// MARK: - UIPopoverPresentationController Delegate methods
extension StockListTableViewController: UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return .FullScreen
}
func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
if let navigationVC = controller.presentedViewController as? UINavigationController,
let preferencesVC = navigationVC.visibleViewController as? PreferencesTableViewController {
// This Bool indicates whether the popover controller should display the bar button item or not
preferencesVC.shouldShowCloseButton = true
}
return controller.presentedViewController
}
}
property:
var shouldShowCloseButton = false
viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
// Close button
if shouldShowCloseButton {
let closeButton = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: #selector(PreferencesTableViewController.doneButtonTapped(_:)))
navigationItem.setRightBarButtonItem(closeButton, animated: true)
}
}
doneButtonTapped:
func doneButtonTapped(sender: UIBarButtonItem) {
navigationController?.dismissViewControllerAnimated(true, completion: nil)
}
For me, this worked perfectly:
on iPhone, I get a view controller presented modally, with a "close" button item in a navigation controller, which allows me to dismiss it
on iPad, I get a popover without a "close" button because with a popover th expected behavior is to tap outside the popover to dismiss it.