web-dev-qa-db-ja.com

iOS 9でプレゼンテーションを行う前に、UIPopoverPresentationControllerにnil以外のsourceViewまたはbarButtonItemを設定する必要があります

カスタム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を設定しています。私はここで何か間違ったことをしていますか?あなたの助けに感謝

5
Francis F

このようなポップオーバープレゼンテーションコントローラーを作成することもでき、それが機能する可能性があります

- (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];
}
8
Martin

UIPopoverPresentationControllerをサブクラス化していますが、Apple recommends そのまま使用します。UIViewControllerを提示すると、UIPopoverPresentationControllerは自動的に作成され、必要に応じて変更することになっています。

myPopoverControllerインスタンスを作成しますが、次の直後にpresentcontentViewControllerすると、Appleは別のインスタンスを作成します。

[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;
3

以下のコードが役立つ可能性があります:

iPadでは、ビューコントローラは新しいUIPopoverPresentationControllerを使用してポップオーバーとして表示されます。次の3つのプロパティのいずれかを使用して、ポップオーバーを表示するためのアンカーポイントを指定する必要があります。

  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];
}
1
Ronak Chaniyara

私が考える最良の方法は、現在のメソッドをオーバーライドすることです

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)
    }
}
1
kkklc