Uipopovercontroller, Xcode 6, iOS 8 Using Swift

UIPopoverController, Xcode 6, IOS 8 using Swift

Here is a simple example for iOS 8. Popover are presented using adaptivity apis in iOS 8.

class PlayerInformationTableViewController: UITableViewController, UIPopoverPresentationControllerDelegate, NSFetchedResultsControllerDelegate{

...

@IBAction func addPopover(sender: UIBarButtonItem){
let playerInformationViewController = PlayerInformationViewController()
playerInformationViewController.modalPresentationStyle = .Popover
playerInformationViewController.preferredContentSize = CGSizeMake(300, 300)

let popoverPresentationViewController = playerInformationViewController.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .Any
popoverPresentationViewController?.delegate = self
popoverPresentationController?.barButtonItem = sender
presentViewController(playerInformationViewController, animated: true, completion: nil)
}

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle{
return .None
}

}

How to make UIPopoverController (Swift)?

* Updated Answer *

class ViewController: UIViewController, UIPopoverControllerDelegate, UIPopoverPresentationControllerDelegate {

@IBOutlet weak var RoutineLabel: UIButton!

@IBAction func RoutineButton(sender: AnyObject) {

switch SDiPhoneVersion.deviceVersion() {
case DeviceVersion.iPad1, DeviceVersion.iPad2, DeviceVersion.iPadMini, DeviceVersion.iPad3, DeviceVersion.iPad4, DeviceVersion.iPadAir, DeviceVersion.iPadMiniRetina:

var popoverViewController = self.storyboard?.instantiateViewControllerWithIdentifier("RoutinesTableViewController") as UITableViewController
popoverViewController.modalPresentationStyle = .Popover
popoverViewController.preferredContentSize = CGSizeMake(300, 300)

let popoverPresentationViewController = popoverViewController.popoverPresentationController

popoverPresentationViewController?.permittedArrowDirections = UIPopoverArrowDirection.Up
popoverPresentationViewController?.delegate = self
popoverPresentationViewController?.sourceView = self.RoutineLabel
popoverPresentationViewController?.sourceRect = CGRectMake(RoutineLabel.frame.width / 2, RoutineLabel.frame.height,0,0)

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

default:

println("iPhones")

}

}
}

Notes:

  • my PopPoverViewController is a UITableViewController
  • I use SDiPhoneVersion.deviceVersion to check for device version
  • I use a button to trigger it
  • I make the start of my pop up depend on RoutineLabel.frame

How to present popover properly in iOS 8

Okay, A housemate took a look at it and figured it out:

 func addCategory() {

var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
var nav = UINavigationController(rootViewController: popoverContent)
nav.modalPresentationStyle = UIModalPresentationStyle.Popover
var popover = nav.popoverPresentationController
popoverContent.preferredContentSize = CGSizeMake(500,600)
popover.delegate = self
popover.sourceView = self.view
popover.sourceRect = CGRectMake(100,100,0,0)

self.presentViewController(nav, animated: true, completion: nil)

}

That's the way.

You don't talk to the popover itself anymore, you talk to the view controller inside of it to set the content size, by calling the property preferredContentSize

iOS 8 : Disable UIBarButtonItem when shown inside a popover

I finally found how to solve that issue :

  • In the storyboard, I removed the "close" bar button item in the navigation bar of the view controller I want to display as a popover on iPad and a modal VC on iPhone. So now this controller is embedded in a navigation controller, but without a "close" button.
    Sample Image
  • In the caller view controller (the one which has a bar button item to call the popover), I added the following code in the prepareForSegue (my segue is a Popover segue by the way)

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

  • I added the following extension so that the caller view controler conforms to UIPopoverPresentationControllerDelegate protocol

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
}

}


  • Finally, in the called view controller (which is a popover on iPad but modal on iPhone), I added the following code:

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.

UIPopoverController for iphone not working?

Edit: As stated by Soberman, since iOS 8 it is possible to present popovers on iPhone using public APIs, so this answer is probably not relevant anymore.


As stated in Apple's documentation on UIPopoverController:

Popover controllers are for use exclusively on iPad devices.

So there is no way to use this class in iPhone application unfortunately. But there are a couple of custom third-party implementations of the functionality provided by UIPopoverController which add iPhone support and more. See https://github.com/50pixels/FPPopover for example.

Edit: There also is another highly customizable popover implementation for both iPhone/iPad worth checking out: https://github.com/nicolaschengdev/WYPopoverController.

How to reach UIPopoverController from its content view controller?

Good Option : Use delegate to dissmiss popover from contentView.

Another option : In iOS 8, you can dismiss the popover by using dismissViewControllerAnimated:completion: from within the popover. Note it doesn't work in iOS 7.

UIPopoverController for iphone in ios8 shows white screen

Try to use the new iOS 8 API for popovers.

pickerController = [[UIViewController alloc] init];
UIView *viewV = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 160)];
[viewV setBackgroundColor:[UIColor clearColor]];

UIPopoverPresentationController *popOverController = pickerController .popoverPresentationController;
popOverController.popoverContentSize = CGSizeMake(150, 160);
[popOverController setDelegate:self];

popOverController.sourceView = self.view;
popOverController.sourceRect = sender.frame;
popOverController.permittedArrowDirections = UIPopoverArrowDirectionUp;

[self presentViewController:popOverController
animated:YES
completion:nil];


Related Topics



Leave a reply



Submit