Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - UIPopoverController in iOS 8

I'm trying to add a simple popoverController to my iphone app, and I'm currently struggling with the classic "blank screen" which covers everything when I tap the button.

My code looks like this:

@IBAction func sendTapped(sender: UIBarButtonItem) {


    var popView = PopViewController(nibName: "PopView", bundle: nil)

    var popController = UIPopoverController(contentViewController: popView)

    popController.popoverContentSize = CGSize(width: 3, height: 3)

    popController.presentPopoverFromBarButtonItem(sendTappedOutl, permittedArrowDirections: UIPopoverArrowDirection.Up, animated: true)

    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle {
        // Return no adaptive presentation style, use default presentation behaviour
        return .None
    }

}

The adaptivePresentationStyleForPresentationController-function was just something I added because I read somewhere that this is what you need to implement to get this function on the iphone. But still: there is still a blank image covering the whole screen, and I do not know how to fix it.

Any suggestions would be appreciated.

like image 729
martin Avatar asked Dec 27 '14 18:12

martin


People also ask

How do I present Viewcontroller in popover Swift?

In the Bar Button Item section Change the System Item to Action. Next, Drag a new View Controller from the Object Library on to the Storyboard. Drag a Text View from the Object Library at the top of this View Controller. This View Controller will be displayed in the popover.

What is Popoverpresentationcontroller in Swift?

The nearest popover presentation controller that is managing the current view controller.


1 Answers

The solution I implemented for this is based on an example presented in the 2014 WWDC session View Controller Advancements in iOS 8 (see the slide notes). Note that you do have to implement the adaptivePresentationStyleForPresentationController function as a part of the UIPopoverPresentationControllerDelegate, but that function should be outside of your sendTapped function in your main view controller, and you must specify UIPopoverPresentationControllerDelegate in your class declaration line in that file to make sure that your code modifies that behaviour. I also took the liberty to separate out the logic to present a view controller in a popover into its own function and added a check to make sure the function does not present the request view controller if it is already presented in the current context.

So, your solution could look something like this:

// ViewController must implement UIPopoverPresentationControllerDelegate
class TheViewController: UIViewController, UIPopoverPresentationControllerDelegate {
    // ...
    // The contents of TheViewController class
    // ...

    @IBAction func sendTapped(sender: UIBarButtonItem) {
        let popView = PopViewController(nibName: "PopView", bundle: nil)
        self.presentViewControllerAsPopover(popView, barButtonItem: sender)
    }

    func presentViewControllerAsPopover(viewController: UIViewController, barButtonItem: UIBarButtonItem) {
        if let presentedVC = self.presentedViewController {
            if presentedVC.nibName == viewController.nibName {
                // The view is already being presented
                return
            }
        }
        // Specify presentation style first (makes the popoverPresentationController property available)
        viewController.modalPresentationStyle = .Popover
        let viewPresentationController = viewController.popoverPresentationController?
        if let presentationController = viewPresentationController {
            presentationController.delegate                 = self
            presentationController.barButtonItem            = barButtonItem
            presentationController.permittedArrowDirections = .Up
        }
        viewController.preferredContentSize = CGSize(width: 30, height: 30)

        self.presentViewController(viewController, animated: true, completion: nil)
    }

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

Real world implementation

I implemented this approach for input validation on a sign up form in an in-progress app that I host on Github. I implemented it as extensions to UIVIewController in UIViewController+Extensions.swift. You can see it in use in the validation functions in AuthViewController.swift. The presentAlertPopover method takes a string and uses it to set the value of a UILabel in a GenericAlertViewController that I have set up (makes it easy to have dynamic text popovers). But the actual popover magic all happens in the presentViewControllerAsPopover method, which takes two parameters: the UIViewController instance to be presented, and a UIView object to use as the anchor from which to present the popover. The arrow direction is hardcoded as UIPopoverArrowDirection.Up, but that wouldn’t be hard to change.

like image 185
Andrew Patton Avatar answered Nov 15 '22 03:11

Andrew Patton