How to present popover properly in iOS 8

I'm trying to add a UIPopoverView to my Swift iOS 8 app, but I am unable to access the PopoverContentSize property, as the popover does not show in the correct shape. my code:

var popover: UIPopoverController? = nil


func addCategory() {


var newCategory = storyboard.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
var nav = UINavigationController(rootViewController: newCategory)
popover = UIPopoverController(contentViewController: nav)
popover!.setPopoverContentSize(CGSizeMake(550, 600), animated: true)
popover!.delegate = self
popover!.presentPopoverFromBarButtonItem(self.navigationItem.rightBarButtonItem, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}

output:

enter image description here

When I am doing the same thing through UIPopoverPresentationController, I still don't get it done. this is my code:

func addCategory() {


var popoverContent = self.storyboard.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
var nav = UINavigationController(rootViewController: popoverContent)
nav.modalPresentationStyle = UIModalPresentationStyle.Popover
var popover = nav.popoverPresentationController as UIPopoverPresentationController
popover.delegate = self
popover.popoverContentSize = CGSizeMake(1000, 300)
popover.sourceView = self.view
popover.sourceRect = CGRectMake(100,100,0,0)


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


}

I get the exact same output.

How do I customize the size of my popover? Any help would be highly appreciated!

193916 次浏览

一个室友看了一眼,发现了:

 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)


}

就是这样。

您不再与 popover 本身交谈,而是通过调用属性 preferredContentSize与其内部的视图控制器交谈来设置内容大小

我发现了一个完整的例子,如何让这一切工作,以便您可以 always显示一个弹出窗口,无论设备/方向 https://github.com/frogcjn/AdaptivePopover_iOS8_Swift

The key is to implement UIAdaptivePresentationControllerDelegate

func adaptivePresentationStyleForPresentationController(PC: UIPresentationController!) -> UIModalPresentationStyle {
// This *forces* a popover to be displayed on the iPhone
return .None
}

然后扩展上面的例子(来自《想象数字》) :

nav.popoverPresentationController!.delegate = implOfUIAPCDelegate

This is best explained on the IOS8日常博客

简而言之,一旦您将 UIViewController 的 modalPresentationStyle 设置为。Popover,您可以通过控制器的 popoverPresentationController 属性获得 UIPopoverPresentationClass (一个新的 iOS8类)。

实际上比那要简单得多。在情节串连板中,您应该创建您想要作为弹出窗口使用的视图控制器,并像往常一样为其创建一个视图控制器类。从你想要打开弹出窗口的对象开始进行如下所示的转换,在这个例子中是名为“ Config”的 UIBarButton

enter image description here

在“主视图控制器”中实现 UIPopoverPresentationControllerDelegate和委托方法:

func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
//do som stuff from the popover
}

Override the prepareForSeque method like this:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//segue for the popover configuration window
if segue.identifier == "yourSegueIdentifierForPopOver" {
if let controller = segue.destinationViewController as? UIViewController {
controller.popoverPresentationController!.delegate = self
controller.preferredContentSize = CGSize(width: 320, height: 186)
}
}
}

你完蛋了。你现在可以像对待其他视图一样对待 Popover 视图。添加领域和什么不!通过使用 UIPopoverPresentationController中的 popoverPresentationController.presentedViewController方法获得内容控制器。

同样在 iPhone 上,你必须覆盖

func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {


return UIModalPresentationStyle.none
}

我在上面做了一个 Objective-C 版本的“想象数字”的快速回答。我不认为我遗漏了什么,因为它似乎在初步测试工作,如果你发现了什么让我知道,我会更新它

-(void) presentPopover
{
YourViewController* popoverContent = [[YourViewController alloc] init]; //this will be a subclass of UIViewController
UINavigationController* nav =  [[UINavigationController alloc] initWithRootViewController:popoverContent];
nav.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* popover = nav.popoverPresentationController;
popoverContent.preferredContentSize = CGSizeMake(500,600);
popover.delegate = self;
popover.sourceRect = CGRectMake(100,100,0,0); //I actually used popover.barButtonItem = self.myBarButton;


[self presentViewController:nav animated:YES completion:nil];
}

Here i Convert "Joris416" Swift Code to Objective-c,

-(void) popoverstart
{
ViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"PopoverView"];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:controller];
nav.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = nav.popoverPresentationController;
controller.preferredContentSize = CGSizeMake(300, 200);
popover.delegate = self;
popover.sourceView = self.view;
popover.sourceRect = CGRectMake(100, 100, 0, 0);
popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:nav animated:YES completion:nil];
}


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

记得注意力不集中
UIPopoverPresentationControllerDelegate, UIAdaptivePresentationControllerDelegate

Swift 2.0

我在故事板中制作了一个 ViewController,与 PopOverViewController 类相关。

import UIKit


class PopOverViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.preferredContentSize = CGSizeMake(200, 200)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "dismiss:")
}
func dismiss(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}

查看 ViewController:

//  ViewController.swift


import UIKit


class ViewController: UIViewController, UIPopoverPresentationControllerDelegate
{
func showPopover(base: UIView)
{
if let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("popover") as? PopOverViewController {


let navController = UINavigationController(rootViewController: viewController)
navController.modalPresentationStyle = .Popover


if let pctrl = navController.popoverPresentationController {
pctrl.delegate = self


pctrl.sourceView = base
pctrl.sourceRect = base.bounds


self.presentViewController(navController, animated: true, completion: nil)
}
}
}
override func viewDidLoad(){
super.viewDidLoad()
}
@IBAction func onShow(sender: UIButton)
{
self.showPopover(sender)
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return .None
}
}

注意: func showPopover (base: UIView)方法应该放在 ViewDidLoad 之前。希望它有帮助!

在 iOS9中 UIPopoverController 是折旧的,所以可以使用下面的代码对于 iOS9.x 以上的 Objective-C 版本,

- (IBAction)onclickPopover:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *viewController = [sb instantiateViewControllerWithIdentifier:@"popover"];


viewController.modalPresentationStyle = UIModalPresentationPopover;
viewController.popoverPresentationController.sourceView = self.popOverBtn;
viewController.popoverPresentationController.sourceRect = self.popOverBtn.bounds;
viewController.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:viewController animated:YES completion:nil]; }

在 Viewcontroller 中实现 UIAdaptivePresentationControllerGenerate。 然后加上:

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

Xcode 9.1/Swift 4我的两分钱。

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {


override func viewDidLoad(){
super.viewDidLoad()


let when = DispatchTime.now() + 0.5


DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in
// to test after 05.secs... :)
self.showPopover(base: self.view)


})


}




func showPopover(base: UIView) {
if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "popover") as? PopOverViewController {


let navController = UINavigationController(rootViewController: viewController)
navController.modalPresentationStyle = .popover


if let pctrl = navController.popoverPresentationController {
pctrl.delegate = self


pctrl.sourceView = base
pctrl.sourceRect = base.bounds


self.present(navController, animated: true, completion: nil)
}
}
}




@IBAction func onShow(sender: UIButton){
self.showPopover(base: sender)
}


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

并在以下方面进行实验:

功能自适应演示风格..。

    return .popover

表格。 等等。

下面有一个相当全面的指南,说明如何配置和显示弹出窗口

总之,一个可行的实现(对 Swift 4.2的原始文章语法进行了一些更新) ,然后从其他地方调用,类似于以下内容:

func showPopover(ofViewController popoverViewController: UIViewController, originView: UIView) {
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover
if let popoverController = popoverViewController.popoverPresentationController {
popoverController.delegate = self
popoverController.sourceView = originView
popoverController.sourceRect = originView.bounds
popoverController.permittedArrowDirections = UIPopoverArrowDirection.any
}
self.present(popoverViewController, animated: true)
}

A lot of this was already covered in the answer from @mmc, but the article helps to explain some of those code elements used, and also show how it could be expanded.

它还提供了很多额外的细节,关于使用委托来处理 iPhone 和 iPad 的演示风格,以及允许在全屏显示时取消弹出窗口。再次为 Swift 4.2更新:

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


func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
if traitCollection.horizontalSizeClass == .compact {
return UIModalPresentationStyle.none
//return UIModalPresentationStyle.fullScreen
}
//return UIModalPresentationStyle.fullScreen
return UIModalPresentationStyle.none
}


func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
switch style {
case .fullScreen:
let navigationController = UINavigationController(rootViewController: controller.presentedViewController)
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: self, action: #selector(doneWithPopover))
navigationController.topViewController?.navigationItem.rightBarButtonItem = doneButton
return navigationController
default:
return controller.presentedViewController
}
}


// As of Swift 4, functions used in selectors must be declared as @objc
@objc private func doneWithPopover() {
self.dismiss(animated: true, completion: nil)
}

希望这个能帮上忙。

给那些想学习的人!

我为那些想学习和使用 Popover 视图的人创建了一个开源项目。你可以在这里找到项目。https://github.com/tryWabbit/KTListPopup

KTListNewResize

 var popoverContent = (self.storyboard?.instantiateViewController(withIdentifier: "WhatsNewViewController"))! as UIViewController
var nav = UINavigationController(rootViewController: popoverContent)
nav.modalPresentationStyle = UIModalPresentationStyle.popover
var popover = nav.popoverPresentationController
popoverContent.preferredContentSize = CGSize(width: 500, height: 100)
popover?.delegate = self
popover?.sourceView = self.view
popover?.sourceRect = CGRectMake(100,100,0,0)


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