iPhone 上的 UIPopoverPresentationController 不产生弹出框
UIPopoverPresentationController on iPhone doesn't produce popover
我正在尝试在我的 iPhone 应用程序中实施新的 UIPopoverPresentationController
(使用 Objective C)。我想要的是一个简单的弹出窗口,带有一个从启动按钮发出的表格视图。
--编辑--
这是我的 REVISED 代码,改编自文档中的研究,SO,以及以下评论中的输入:
- (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;
这是我的故事板联播:
然而,这只是以模态方式呈现一个表格视图,从底部上升并占用整个屏幕。
我已经在谷歌上搜索过,并仔细查看了 SO,但看来我并不是唯一一个对我希望解决 iPhone 的棘手问题感到困惑的人。
任何人都可以看到我的代码中的错误或指导我查看清晰的教程吗?我看过了,但也许 API 太新了,还没有人了解它。
谢谢!
第二次编辑:
以下是上述代码的结果。我减小了 View Controller 中 tableview 的大小,我希望它以弹出窗口的形式呈现。我将背景涂成灰色,只是为了阐明显示的内容而不是弹出框。
步骤:
A) Link 使用 Present As Popover
segue 类型将您的 UIButton
连接到弹出窗口的视图控制器。实际上,我必须创建一个新项目才能显示它,但这可能与基本 SDK 有关。
B) 使包含 UIButton
的视图控制器符合 <UIPopoverPresentationControllerDelegate>
。例如。在您的 MyViewController.m
文件中添加:
@interface MyViewController () <UIPopoverPresentationControllerDelegate>
C) 将下面的方法添加到包含 UIButton
:
的视图控制器
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
D) 将以下内容添加到您的 prepareForSegue:sender:
中替换您的 segue.identifier
检查:
if ([segue.identifier isEqualToString:@"CatSelectSegue"]) {
UIViewController *dvc = segue.destinationViewController;
UIPopoverPresentationController *controller = dvc.popoverPresentationController;
if (controller) {
controller.delegate = self;
}
}
代码测试并证明其有效:
编辑:我的测试应用程序 TPOPViewController.m 魔法发生的文件:
#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
我的测试故事板也是:
显然上述方法不再适用于 iOS9/Xcode7。这是因为如果您使用 Interface Builder 将 segue 样式设置为 "Popover",Xcode 在编译您的应用程序时会忽略它。此外,它会在您下次打开项目时自动将 segue 设置回 "Push"。如果您有像 Git 这样的版本控制软件,您将能够观察到正在进行的这种不需要的更改。
但是,如果您手动显示您想要显示为弹出窗口。示例 Swift 代码:
// 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)
}
}
显示来自 iPhone/iPad 的 UIModalPresentationStyle 弹出窗口:
-(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;
}
SWIFT 3.X
这将在屏幕中央显示弹出窗口
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
}
}
**Made a barbutton item like this** -
let dotImage = UIImage(named: "dot")?.withRenderingMode(.alwaysOriginal) let searchImage = UIImage(named: "search")?.withRenderingMode(.alwaysOriginal) // let shareImageButton = UIBarButtonItem(image: shareImage, style: .plain, target: self, action: #selector(didTapshareImageButton(sender:))) let dotImageButton = UIBarButtonItem(image: dotImage, style: .plain, target: self, action: #selector(didTapdotImageButton(sender:))) let searchButton = UIBarButtonItem(image: searchImage, style: .plain, target: self, action: #selector(didTapSearchButton(sender:)))
**Added popover on this -**
@objc func didTapdotImageButton(sender: UIBarButtonItem){
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ShareVC")
vc.modalPresentationStyle = .popover
let popover: UIPopoverPresentationController = vc.popoverPresentationController!
popover.barButtonItem = sender
popover.delegate = self
sender.image = UIImage(named: "close")?.withRenderingMode(.alwaysOriginal)
present(vc, animated: true, completion:nil)
}
我正在尝试在我的 iPhone 应用程序中实施新的 UIPopoverPresentationController
(使用 Objective C)。我想要的是一个简单的弹出窗口,带有一个从启动按钮发出的表格视图。
--编辑--
这是我的 REVISED 代码,改编自文档中的研究,SO,以及以下评论中的输入:
- (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;
这是我的故事板联播:
然而,这只是以模态方式呈现一个表格视图,从底部上升并占用整个屏幕。
我已经在谷歌上搜索过,并仔细查看了 SO,但看来我并不是唯一一个对我希望解决 iPhone 的棘手问题感到困惑的人。
任何人都可以看到我的代码中的错误或指导我查看清晰的教程吗?我看过了,但也许 API 太新了,还没有人了解它。
谢谢!
第二次编辑:
以下是上述代码的结果。我减小了 View Controller 中 tableview 的大小,我希望它以弹出窗口的形式呈现。我将背景涂成灰色,只是为了阐明显示的内容而不是弹出框。
步骤:
A) Link 使用 Present As Popover
segue 类型将您的 UIButton
连接到弹出窗口的视图控制器。实际上,我必须创建一个新项目才能显示它,但这可能与基本 SDK 有关。
B) 使包含 UIButton
的视图控制器符合 <UIPopoverPresentationControllerDelegate>
。例如。在您的 MyViewController.m
文件中添加:
@interface MyViewController () <UIPopoverPresentationControllerDelegate>
C) 将下面的方法添加到包含 UIButton
:
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
D) 将以下内容添加到您的 prepareForSegue:sender:
中替换您的 segue.identifier
检查:
if ([segue.identifier isEqualToString:@"CatSelectSegue"]) {
UIViewController *dvc = segue.destinationViewController;
UIPopoverPresentationController *controller = dvc.popoverPresentationController;
if (controller) {
controller.delegate = self;
}
}
代码测试并证明其有效:
编辑:我的测试应用程序 TPOPViewController.m 魔法发生的文件:
#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
我的测试故事板也是:
显然上述方法不再适用于 iOS9/Xcode7。这是因为如果您使用 Interface Builder 将 segue 样式设置为 "Popover",Xcode 在编译您的应用程序时会忽略它。此外,它会在您下次打开项目时自动将 segue 设置回 "Push"。如果您有像 Git 这样的版本控制软件,您将能够观察到正在进行的这种不需要的更改。
但是,如果您手动显示您想要显示为弹出窗口。示例 Swift 代码:
// 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)
}
}
显示来自 iPhone/iPad 的 UIModalPresentationStyle 弹出窗口:
-(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;
}
SWIFT 3.X
这将在屏幕中央显示弹出窗口
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
}
}
**Made a barbutton item like this** -
let dotImage = UIImage(named: "dot")?.withRenderingMode(.alwaysOriginal) let searchImage = UIImage(named: "search")?.withRenderingMode(.alwaysOriginal) // let shareImageButton = UIBarButtonItem(image: shareImage, style: .plain, target: self, action: #selector(didTapshareImageButton(sender:))) let dotImageButton = UIBarButtonItem(image: dotImage, style: .plain, target: self, action: #selector(didTapdotImageButton(sender:))) let searchButton = UIBarButtonItem(image: searchImage, style: .plain, target: self, action: #selector(didTapSearchButton(sender:)))
**Added popover on this -**
@objc func didTapdotImageButton(sender: UIBarButtonItem){
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ShareVC")
vc.modalPresentationStyle = .popover
let popover: UIPopoverPresentationController = vc.popoverPresentationController!
popover.barButtonItem = sender
popover.delegate = self
sender.image = UIImage(named: "close")?.withRenderingMode(.alwaysOriginal)
present(vc, animated: true, completion:nil)
}