16

I wish to create a small popover about 50x50px from a UIButton. I have seen methods using adaptive segue's but I have my size classes turn of thus meaning I can not use this features!

How else can I create this popover? Can I create it with code inside my button IBACtion? Or is there still a way I can do this with storyboards?

Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
user4671001
  • 309
  • 2
  • 4
  • 12

4 Answers4

15

You can do one of the following two options :

  • Create an action for the UIButton in your UIViewController and inside present the ViewController you want like a Popover and your UIViewController has to implement the protocol UIPopoverPresentationControllerDelegate, take a look in the following code :

    @IBAction func showPopover(sender: AnyObject) {
    
        var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardIdentifier") as! UIViewController
    
        popoverContent.modalPresentationStyle = .Popover
        var popover = popoverContent.popoverPresentationController
    
        if let popover = popoverContent.popoverPresentationController {
    
           let viewForSource = sender as! UIView
           popover.sourceView = viewForSource
    
           // the position of the popover where it's showed
           popover.sourceRect = viewForSource.bounds
    
           // the size you want to display
           popoverContent.preferredContentSize = CGSizeMake(200,500)
           popover.delegate = self
        }            
    
        self.presentViewController(popoverContent, animated: true, completion: nil)
    }
    
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
       return .None
    }
    

    According to the book of @matt Programming iOS 8:

    A popover presentation controller, in iOS 8, is a presentation controller (UIPresentationController), and presentation controllers are adaptive. This means that, by default, in a horizontally compact environment (i.e. on an iPhone), the .Popover modal presentation style will be treated as .FullScreen. What appears as a popover on the iPad will appear as a fullscreen presented view on the iPhone, completely replacing the interface.

    To avoid this behavior in the iPhone you need to implement the delegate method adaptivePresentationStyleForPresentationController inside your UIViewController to display the Popover correctly.

  • The other way in my opinion is more easy to do, and is using Interface Builder, just arrange from the UIButton to create a segue to the ViewController you want and in the segue select the Popover segue.

I hope this help you.

Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
  • Thanks for this! The first example works but it dosnt seem to chaange the size. The popover just comes up full screen. I think the second way you explained would be a better way.. But once again I get a error couldn't comply connection IBCocoaTouchoutlet anchor View. Could you give me some code that would go along with the second way you explained? – user4671001 Mar 21 '15 at 20:34
  • @user4671001 I don't understand, in the seconde way you not need to set the anchoView for nothing – Victor Sigler Mar 23 '15 at 14:57
  • 4
    popover shows as fullscreen modal on iphones, you can disable this by adding this function:`func adaptivePresentationStyleForPresentationController(PC: UIPresentationController!) -> UIModalPresentationStyle { // This *forces* a popover to be displayed on the iPhone return .None }` – user1076813 May 26 '15 at 03:23
  • Same in Swift2. Xcode shows an error about the anchor. Any solutions? – Lukesivi Nov 05 '15 at 14:01
  • @lukesIvi You not have to set the anchor in the above code and the code works in iOS 9 and Swift2. – Victor Sigler Nov 05 '15 at 16:22
  • Can you send a repository over github? I'm trying to go one from viewControllerKOne to another while passing a URL from viewControllerOne to the url VC and then going back to the VCOne. I don't want to send data back and forth. Instead, I just want to send to the URL VC and then go right back without having to reload data to the VCOne. Any ideas? – Lukesivi Nov 05 '15 at 16:48
  • Just give me a moment I'll upload a repository and I update some topics in my answer. – Victor Sigler Nov 05 '15 at 16:50
  • @lukesIvi See updated answer and if you need the repo yet let me know and I'll upload it to Github – Victor Sigler Nov 05 '15 at 21:09
  • Thanks, i got it working in a similar fashion but with less code. I could post the answer/the gist if anyone is interested. PS, this did help though. – Lukesivi Nov 06 '15 at 15:54
  • @VictorSigler can you provide this code in objective-c? check my question https://stackoverflow.com/questions/51308025/how-to-create-popover-clicked-on-button – Chandan Jee Jul 12 '18 at 14:23
11

Swift 4 Here is fully working code. So here you will see popup window with size of 250x250:

    import UIKit

    class ViewController: UIViewController {

        @IBOutlet weak var button: UIButton!

        override func viewDidLoad() {
            super.viewDidLoad()

// in case if you don't want to make it via IBAction
            button.addTarget(self, action: #selector(tapped), for: .touchUpInside)
        }

        @objc
        private func tapped() {

            guard let popVC = storyboard?.instantiateViewController(withIdentifier: "popVC") else { return }

            popVC.modalPresentationStyle = .popover

            let popOverVC = popVC.popoverPresentationController
            popOverVC?.delegate = self
            popOverVC?.sourceView = self.button
            popOverVC?.sourceRect = CGRect(x: self.button.bounds.midX, y: self.button.bounds.minY, width: 0, height: 0)
            popVC.preferredContentSize = CGSize(width: 250, height: 250)

            self.present(popVC, animated: true)
        }
    }


// This is we need to make it looks as a popup window on iPhone
    extension ViewController: UIPopoverPresentationControllerDelegate {

        func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
            return .none
        }
    }

Take into attention that you have to provide popVC identifier to one viewController you want to present as a popup.

Hope that helps!

wm.p1us
  • 2,019
  • 2
  • 27
  • 38
  • can you provide this code in objective-c? Please check my question https://stackoverflow.com/questions/51308025/how-to-create-popover-clicked-on-button – Chandan Jee Jul 12 '18 at 14:22
2

Here you can present a popover on button click.

func addCategory( _ sender : UIButton) {

        var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
        var nav = UINavigationController(rootViewController: popoverContent)
        nav.modalPresentationStyle = UIModalPresentationStyle.Popover
        var popover = nav.popoverPresentationController
        popoverContent.preferredContentSize = CGSizeMake(50,50)
        popover.delegate = self
        popover.sourceView = sender
        popover.sourceRect = sender.bounds

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

    }
Usman Javed
  • 2,437
  • 1
  • 17
  • 26
1

Swift 4 Version

Doing most work from the storyboard

I added a ViewController, went to it's attribute inspector and ticked the "Use Preferred Explicit size". After that I changed the Width and Height values to 50 each.

Once this was done I ctrl clicked and dragged from the Button to the ViewController I added choosing "Present as Popover" and naming the segue Identifier as "pop"

Went to the ViewController where I had my Button and added the following code:

class FirstViewController: UIViewController, UIPopoverPresentationControllerDelegate {
    @IBOutlet weak var popoverButton: UIButton! // the button

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "pop" {
            let popoverViewController = segue.destination
            popoverViewController.modalPresentationStyle = .popover
            popoverViewController.presentationController?.delegate = self
            popoverViewController.popoverPresentationController?.sourceView = popoverButton
            popoverViewController.popoverPresentationController?.sourceRect  = CGRect(x: 0, y: 0, width: popoverButton.frame.size.width, height: popoverButton.frame.size.height)
        }
    }
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.none
    }



    override func viewDidLoad() {
        super.viewDidLoad()
    }

}
Korpel
  • 2,432
  • 20
  • 30