21

我正在尝试使用自定义 UIPopoverPresentationController 类显示一个弹出窗口。但它崩溃并出现错误(<UIPopoverPresentationController: 0x7a772950>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.下面是我发生崩溃的按钮单击代码。

- (IBAction)showPopup:(UIButton *)sender {
ViewController *contentViewController = [[ViewController alloc] init];

    contentViewController.preferredContentSize = CGSizeMake(200, 200);
    contentViewController.modalPresentationStyle = UIModalPresentationPopover;
    myPopoverController *popOver = [[myPopoverController alloc]initWithPresentedViewController:contentViewController presentingViewController:self andTintColor:[UIColor lightGrayColor]];

    popOver.delegate = self;
    popOver.permittedArrowDirections = UIPopoverArrowDirectionUp;
    popOver.sourceRect = sender.frame;
    popOver.sourceView = self.view;
    [self presentViewController:contentViewController animated: YES completion: nil];
}

下面是我的自定义 UIPopoverPresentationController 的示例

myPopoverController.h file

@interface myPopoverController : UIPopoverPresentationController

@property (readonly) UIColor *tintColor;


-(instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController andTintColor:(UIColor *)aTintColor;

@end


myPopoverController.m file

//Some code for UIPopoverBackgroundView

-(instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController
{

    self = [self initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController andTintColor: [UIColor redColor]];

    return self;
}


-(instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController andTintColor:(UIColor *)aTintColor
{

    self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController];

    if (!self) {
        return nil;
    }

    [super setPopoverBackgroundViewClass: [myPopoverControllerBackgroundView class]];
    tintColor = aTintColor;


    return self;
}

我没有条形按钮,但我正在设置 sourceView。我在这里做错了吗?感谢你的帮助

4

6 回答 6

11

您也可以像这样创建一个弹出式演示控制器,它可能会起作用

- (IBAction)showPopup:(UIButton *)sender {

ViewController *contentViewController = [[ViewController alloc] init];
    contentViewController.preferredContentSize = CGSizeMake(200, 200);
    contentViewController.modalPresentationStyle = UIModalPresentationPopover;

UIPopoverPresentationController *popoverpresentationController = contentViewController.popoverPresentationController;
    popoverpresentationController.delegate = self;
    popoverpresentationController.permittedArrowDirections = UIPopoverArrowDirectionUp;
    popoverpresentationController.sourceRect = sender.bounds;
    popoverpresentationController.sourceView = sender;
    [self presentViewController:contentViewController animated: YES completion: nil];
}
于 2017-04-07T14:24:05.683 回答
5

如果 sourceView 为 null,只需添加验证

UIActivityViewController * avc = [[UIActivityViewController alloc] initWithActivityItems:shareItems applicationActivities:nil];
if(avc.popoverPresentationController){
    avc.popoverPresentationController.sourceView = self.view;
}
[self presentViewController:avc animated:YES completion:nil];

看到这个帖子

于 2021-02-03T20:52:55.573 回答
4

您正在继承,UIPopoverPresentationController但 Apple建议按原样使用它们。一旦您提出 a UIViewController, aUIPopoverPresentationController将被自动创建,您应该根据需要对其进行修改。

您创建一个myPopoverController实例,但 Apple 在您之后创建另一个present实例contentViewController

[self presentViewController:contentViewController animated: YES completion: nil];

这个新UIPopoverPresentationController的缺少sourceView并抛出异常。

请尝试以下代码:

ViewController *contentViewController = [[ViewController alloc] init];

// Present the view controller using the popover style.
contentViewController.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:contentViewController 
                   animated:YES 
                 completion:nil];

// Get the popover presentation controller and configure it.
UIPopoverPresentationController *presentationController =[contentViewController popoverPresentationController];
presentationController.permittedArrowDirections = UIPopoverArrowDirectionUp;
presentationController.sourceView = self.view;
presentationController.sourceRect = sender.frame;
于 2017-07-27T09:37:36.207 回答
2

下面的代码可能会有所帮助:

iPad视图控制器中,将使用 new 显示为弹出框UIPopoverPresentationController,它需要使用以下三个属性之一为弹出框的呈现指定一个锚点:

  1. barButtonItem
  2. sourceView
  3. sourceRect

执行以下操作:

//for iPhone
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {

    [self presentViewController:controller animated:YES completion:nil];

}
//for iPad
else {
    // Change Rect as required
    ViewController *contentViewController = [[ViewController alloc] init];

    contentViewController.preferredContentSize = CGSizeMake(200, 200);
    contentViewController.modalPresentationStyle = UIModalPresentationPopover;
    [self presentViewController:contentViewController animated:YES completion:nil];
}
于 2017-03-21T07:21:44.673 回答
2

我认为最好的方法是覆盖当前方法

extension XXXBaseViewController: UIPopoverPresentationControllerDelegate {

    override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        if let popController = viewControllerToPresent.popoverPresentationController,
            popController.sourceView == nil{
            return
        }
        super.present(viewControllerToPresent, animated: flag, completion: completion)
    }
}
于 2019-05-16T07:53:42.553 回答
0

我的两分钱用于活动(以及 swift 5 ..)

..

 let activityViewController = UIActivityViewController(
                activityItems: shareTextAndImg, applicationActivities: [])
 if UIDevice.current.userInterfaceIdiom == .pad {
   activityViewController.popoverPresentationController?.barButtonItem = btn
  }

present(activityViewController, animated: true)
于 2022-02-20T10:21:33.030 回答