UIPopoverPresentationController on iPhone doesn't produce popover

半腔热情 提交于 2019-11-26 07:32:27

问题


I\'m trying to implement the new UIPopoverPresentationController in my iPhone app (using Objective C). What I want is a simple popover with a tableview that emanates from the initiating button.

--Edit--

Here\'s my REVISED code, adapted from research in the docs, SO, and from input in comments below:

- (IBAction)selectCategoryBtn:(UIButton *)sender
{
    [self performSegueWithIdentifier:@\"CatSelectSegue\" sender:self.selCatButton];
}

-(void) prepareForSegue:(UIStoryboardSegue *) segue Sender:(id) sender
{
    if (sender == self.selCatButton)
    {
        if ([segue.identifier isEqualToString:@\"CatSelectSegue\"])
        {
            UIPopoverPresentationController *controller = segue.destinationViewController;
            controller.delegate = self;
            controller.sourceView = self.selCatButton;
            controller.sourceRect = self.selCatButton.frame;
        }
    }
}


-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
    return UIModalPresentationNone;

Here\'s my storyboard hookup:

\"enter

However this simply presents a tableview in a modal fashion, rising up from the bottom and consuming the entire screen.

I\'ve googled, and looked all over SO, but it appears that I\'m not the only one confused by what I\'d hoped would resolve a nettlesome issue for the iPhone.

Can anyone see a glitch in my code or direct me to a clear tutorial? I\'ve looked, but maybe the API is just so new nobody\'s got a handle on it yet.

Thanks!

2nd edit:

Here\'s what gets presented as a result of the code above. I reduced the size of the tableview in the View Controller I expected to be presented as a popover. I colored the background gray, just to clarify what\'s showing up instead of the popover.

\"enter


回答1:


Steps:

A) Link your UIButton to the popover's view controller using the Present As Popover segue type. I actually had to create a new project to get this to appear but it's probably something to do with the base SDK.

B) Make the View Controller containing the UIButton conform to the <UIPopoverPresentationControllerDelegate>. E.g. In your MyViewController.m file add:

@interface MyViewController () <UIPopoverPresentationControllerDelegate>

C) Add the method below to the View Controller containing the UIButton:

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {

    return UIModalPresentationNone;
}

D) Add the following into your prepareForSegue:sender: replacing your segue.identifier check:

if ([segue.identifier isEqualToString:@"CatSelectSegue"]) {
    UIViewController *dvc = segue.destinationViewController;
    UIPopoverPresentationController *controller = dvc.popoverPresentationController;
    if (controller) {
        controller.delegate = self;
    }
}

Code tested and proof it works:

Edit: My test app TPOPViewController.m file where the magic happens:

#import "TPOPViewController.h"

@interface TPOPViewController () <UIPopoverPresentationControllerDelegate>//, UIAdaptivePresentationControllerDelegate>

@end

@implementation TPOPViewController

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    NSString *identifier = segue.identifier;
    if ([identifier isEqualToString:@"popover"]) {
        UIViewController *dvc = segue.destinationViewController;
        UIPopoverPresentationController *ppc = dvc.popoverPresentationController;
        if (ppc) {
            if ([sender isKindOfClass:[UIButton class]]) { // Assumes the popover is being triggered by a UIButton
                ppc.sourceView = (UIButton *)sender;
                ppc.sourceRect = [(UIButton *)sender bounds];
            }
            ppc.delegate = self;
        }
    }
}

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {

    return UIModalPresentationNone;
}

@end

My test storyboard as well:




回答2:


Apparently the above method no longer works with iOS9/Xcode7. This is because if you set the segue style to "Popover" using Interface Builder, Xcode ignores it when it compiles your application. Furthermore, it automatically sets the segue back to "Push" the next time you open your project. If you have version control software like Git, you'll be able to observe this unwanted change being made.

However, it's still possible to get iPad-style popovers on the iPhone if you manually present the view controller that you want to show as a popover. Example Swift code:

//  ViewController.swift
//  PopoverDemo
//
//  Created by bhnascar on 12/2/15.
//  Copyright © 2015 bhnascar. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {

    /* The bar button item that will present the popover. */
    var popoverButton: UIBarButtonItem?

    override func viewDidLoad() {
        super.viewDidLoad()
        popoverButton = UIBarButtonItem(title: "Pop!", style: UIBarButtonItemStyle.Plain, target: self, action: "presentPopover")
        self.navigationItem.rightBarButtonItem = popoverButton
    }

    // Mark: - UIPopoverPresentationControllerDelegate

    func prepareForPopoverPresentation(popoverPresentationController: UIPopoverPresentationController) {
        popoverPresentationController.permittedArrowDirections = .any
        popoverPresentationController.barButtonItem = popoverButton
    }

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

    // Mark: - Callback function for popover button.

    func presentPopover() {
        let popoverContentController = UIViewController()
        popoverContentController.view.backgroundColor = .blue

        // Set your popover size.
        popoverContentController.preferredContentSize = CGSize(width: 300, height: 300)

        // Set the presentation style to modal so that the above methods get called.
        popoverContentController.modalPresentationStyle = .popover

        // Set the popover presentation controller delegate so that the above methods get called.
        popoverContentController.popoverPresentationController!.delegate = self

        // Present the popover.
        self.present(popoverContentController, animated: true, completion: nil)
    }

}



回答3:


SWIFT 3.X

This will show the popover at the center of the screen

class CommonViewController: UIViewController, UIPopoverPresentationControllerDelegate{

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

    func showPopover() {
        let myViewController = UIViewController()
        myViewController.preferredContentSize = CGSize(width: 320, height: 200)
        myViewController.modalPresentationStyle = .popover

        let popOver = myViewController.popoverPresentationController
        popOver?.delegate = self

        self.present(myViewController, animated: true, completion: nil)
        popOver?.permittedArrowDirections = .up
        popOver?.sourceView = self.view

        let rect = CGRect(
            origin: CGPoint(x: self.view.frame.width/2,
                            y: self.view.frame.height/2),
            size: CGSize(width: 1, height: 1)
        )
        popOver?.sourceRect = rect
    }
}



回答4:


To present UIModalPresentationStyle popover from iPhone/iPad:

-(void)menuButtonPressed:(UIButton *)sender {

    self.menuPopoverController = [[DownloadMenuPopoverController alloc] initWithStyle:UITableViewStylePlain];
    self.menuPopoverController.delegate = self;

    self.menuPopoverController.modalPresentationStyle = UIModalPresentationPopover;
    self.menuPopoverController.popoverPresentationController.delegate = self;
    self.menuPopoverController.preferredContentSize = CGSizeMake(250,80);
    self.menuPopoverController.popoverPresentationController.sourceRect = sender.frame;// rect to show view
    self.menuPopoverController.popoverPresentationController.sourceView = self.view;

    UIPopoverPresentationController *popPC = self.menuPopoverController.popoverPresentationController;
    popPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
    popPC.delegate = self;
    [self presentViewController:self.menuPopoverController animated:YES completion:nil];

}

#pragma mark - UIPresentationController Delegate methods

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection {
    return UIModalPresentationNone;
}

- (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style {
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller.presentedViewController];
    return navController;
}


来源:https://stackoverflow.com/questions/28521583/uipopoverpresentationcontroller-on-iphone-doesnt-produce-popover

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!