Why is 'present as popover' segue covering the whole screen?

18,550

Solution 1

The OP uses Objective-C. This answer presents code in swift. Converting swift to Objective-C should be easy.

In the newly added ViewController, under “Simulated Metrics” change “Size” to “Freeform” and “Status Bar” to “None.”

Under “Simulated Size” change your view’s height and width to the actual size you want your popover’s content to be.

Create a segue to the newly added VC. Use segue type as "Present As Popover" and give a name for the segue, for example "popoverSegue".

In the ViewConroller from which this segue is to be triggered, add the UIPopoverPresentationControllerDelegate protocol.

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
}

Override the prepareForSegue function to catch your popover segue. Set the modalPresentationStyle to .Popover to explicitly state that you want a popover and then assign the delegate property of the view’s popoverPresentationController to self:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "popoverSegue" {
            let popoverViewController = segue.destinationViewController as! UIViewController
            popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
            popoverViewController.popoverPresentationController!.delegate = self
        }
    }

Implement the adaptivePresentationStyleForPresentationController function to tell your app that you really want that popover presentation and will accept no substitutions:

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

Following these, I could get a popup on iPhone which is not full screen but the size set for the ViewController.

enter image description here

Source: iPad Style Popovers on the iPhone with Swift

Solution 2

Thanks to Bharat for the great answer, I personally use a UIStoryboardSegue that does pretty much the same thing. That way, I can change the class of the segue in the storyboard, have what I want, and not pollute my controllers:

class AlwaysPopupSegue : UIStoryboardSegue, UIPopoverPresentationControllerDelegate
{
    override init(identifier: String?, source: UIViewController, destination: UIViewController)
    {
        super.init(identifier: identifier, source: source, destination: destination)
        destination.modalPresentationStyle = UIModalPresentationStyle.popover
        destination.popoverPresentationController!.delegate = self
    }
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.none
    }
}

Solution 3

Swift 3-5 version

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "SEGUE_IDENTIFIER" {
            let popoverViewController = segue.destination as! YourViewController
            
            popoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover
            popoverViewController.popoverPresentationController!.delegate = self
        }
    }
    
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.none
    }
    

Solution 4

Swift 4 Version

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "SegueIdentifier" {
            let popoverViewController = segue.destination
            popoverViewController.modalPresentationStyle = .popover
            popoverViewController.presentationController?.delegate = self
     }
}

Don't forget to add

func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.none
    }
Share:
18,550
coal175
Author by

coal175

Updated on July 18, 2022

Comments

  • coal175
    coal175 almost 2 years

    In my project I have a button on the bottom right side of the screen and i added another uiviewcontroller to the storyboard, did control-drag to the uiviewcontroller I wanted as the popover, then set that viewcontroller size to (300, 300) and checked 'use preferred explicit size'. When I load the app and click the button, the entire screen gets covered by the "popover". I also tried to go into the popoverViewController's .m file and set the size but that didn't work either.
    Any ideas?

    Edit: Since it looks like I have to have it be full screen that is fine however I am still running into some other problems I was having earlier. My popup screen will come up and I make the background black and alpha as .5 to make it see through however it'll do the animation, then once the animation is finished the screen will go from .5 opacity to completely black and the only thing I can see is the battery icon thing.

  • SomeGuy
    SomeGuy over 7 years
    This works for me, but I find that the popover is ignoring the view size and just giving me a random size that's like 1/3 the screen size.
  • SomeGuy
    SomeGuy over 7 years
    Ah, solved it. I had to check the box for "Use Preferred Explicit Size"
  • jbbenni
    jbbenni about 6 years
    IMHO this is a better answer, and earns the checkmark.
  • JoeGalind
    JoeGalind about 5 years
    Very elegant approach
  • Codetard
    Codetard about 3 years
    Still saving lives! 🙌