web-dev-qa-db-ja.com

iOS 8 iPhoneのUIPopoverPresentationController

UIPopoverPresentationControllerを使用して、iPhoneでポップオーバーを表示できるかどうかを知っていますか? iPadおよびiPhone用のより統一されたプレゼンテーションコントローラーを作成しようとして、AppleがiOS 8にこの機能を追加したかどうか疑問に思いました。

ベータ版からの質問/回答に問題がないかどうかはわかりません。その場合は削除します。

73
Dave

adaptivePresentationStyleForPresentationController:で利用できるUIPopoverPresentationController.delegateメソッドを使用して、デフォルトの適応動作(コンパクトな水平環境、つまりiPhoneのUIModalPresentationFullScreen)をオーバーライドできます。

UIPresentationControllerはこのメソッドを使用して、使用する新しいプレゼンテーションスタイルを要求します。この場合、UIModalPresentationNoneを返すだけで、UIPopoverPresentationControllerがフルスクリーンではなくポップオーバーとしてレンダリングされます。

ストーリーボードでUIBarButtonItemから "present modally" a UIViewControllerにセグエ設定を使用したポップオーバーの例を次に示します。

class SomeViewController: UIViewController, UIPopoverPresentationControllerDelegate {

    // override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { // Swift < 3.0
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "PopoverSegue" {
            if let controller = segue.destinationViewController as? UIViewController {
                controller.popoverPresentationController.delegate = self
                controller.preferredContentSize = CGSize(width: 320, height: 186)                
            }
        }
    }

    // MARK: UIPopoverPresentationControllerDelegate

    //func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle { // Swift < 3.0
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        // Return no adaptive presentation style, use default presentation behaviour
        return .None
    }
}

このトリックは WWDC 2014セッション214 "View Controller Advancement in iOS8" (36:30)で言及されました

83
Ivan Choo

誰かがコードだけでポップオーバーを表示したい場合は、次のアプローチを使用できます。

目的-C

UIPopoverPresentationControllerのプロパティを宣言します:

@property(nonatomic,retain)UIPopoverPresentationController *dateTimePopover8;

次のメソッドを使用して、UIButtonからポップオーバーを表示します。

- (IBAction)btnSelectDatePressed:(id)sender
{
    UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
    dateVC.preferredContentSize = CGSizeMake(280,200);
    destNav.modalPresentationStyle = UIModalPresentationPopover;
    _dateTimePopover8 = destNav.popoverPresentationController;
    _dateTimePopover8.delegate = self;
    _dateTimePopover8.sourceView = self.view;
    _dateTimePopover8.sourceRect = sender.frame;
    destNav.navigationBarHidden = YES;
    [self presentViewController:destNav animated:YES completion:nil];
}

次のメソッドを使用して、UIBarButtonItemからポップオーバーを表示します。

- (IBAction)btnSelectDatePressed:(id)sender
{
    UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
    dateVC.preferredContentSize = CGSizeMake(280,200);
    destNav.modalPresentationStyle = UIModalPresentationPopover;
    _dateTimePopover8 = destNav.popoverPresentationController;
    _dateTimePopover8.delegate = self;
    _dateTimePopover8.sourceView = self.view;
     CGRect frame = [[sender valueForKey:@"view"] frame];
    frame.Origin.y = frame.Origin.y+20;
    _dateTimePopover8.sourceRect = frame;
    destNav.navigationBarHidden = YES;
    [self presentViewController:destNav animated:YES completion:nil];
}

View Controllerにもこのデリゲートメソッドを実装します:

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

このポップオーバーを閉じるには、View Controllerを閉じます。以下は、View Controllerを閉じるためのコードです。

-(void)hideIOS8PopOver
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

スイフト

次のメソッドを使用して、UIButonからポップオーバーを表示します。

func filterBooks(sender: UIButon)
    {
        let filterVC =  FilterDistanceViewController(nibName: "FilterDistanceViewController", bundle: nil)
        var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
        filterDistanceViewController.preferredContentSize = CGSizeMake(300, 205)
        let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
        popoverPresentationViewController?.permittedArrowDirections = .Any
        popoverPresentationViewController?.delegate = self
        popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
        popoverPresentationViewController!.sourceView = self.view;
        popoverPresentationViewController!.sourceRect = sender.frame

        filterDistanceViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
        filterDistanceViewController.navigationBarHidden = true
        self.presentViewController(filterDistanceViewController, animated: true, completion: nil)
    }

次のメソッドを使用して、UIBarButtonItemからポップオーバーを表示します。

func filterBooks(sender: UIBarButtonItem)
    {
        let filterVC =  FilterDistanceViewController(nibName: "FilterDistanceViewController", bundle: nil)
        var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
        filterDistanceViewController.preferredContentSize = CGSizeMake(300, 205)
        let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
        popoverPresentationViewController?.permittedArrowDirections = .Any
        popoverPresentationViewController?.delegate = self
        popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
        popoverPresentationViewController!.sourceView = self.view;
        var frame:CGRect = sender.valueForKey("view")!.frame
        frame.Origin.y = frame.Origin.y+20
        popoverPresentationViewController!.sourceRect = frame

        filterDistanceViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
        filterDistanceViewController.navigationBarHidden = true
        self.presentViewController(filterDistanceViewController, animated: true, completion: nil)
    }

View Controllerにもこのデリゲートメソッドを実装します:

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle{
        return .None
    }

デリゲートUIPopoverPresentationControllerDelegateを.h/.m/.Swiftファイルに追加してください

73
Desert Rose

問題: iPhoneポップオーバーはフルスクリーンを表示し、preferredContentSize値を尊重しません。

SOLUTION: UIPopoverPresentationController ClassリファレンスでAppleが提案するものに反して、View Controllerafterを提示するポップオーバープレゼンテーションコントローラーへの参照と構成。

// Get the popover presentation controller and configure it.
//...

// Present the view controller using the popover style.
[self presentViewController:myPopoverViewController animated: YES completion: nil]; 
10
agandi

回避策を見つけました。

Xcode6.1では、presentationController.delegateの代わりにpopoverPresentationController.delegateを使用します。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier compare:@"showPopOver"] == NSOrderedSame) {
        UINavigationController * nvc = segue.destinationViewController;
        UIPresentationController * pc = nvc.presentationController;
        pc.delegate = self;
    }
}

#pragma mark == UIPopoverPresentationControllerDelegate ==
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
    return UIModalPresentationNone;
}

WWDC 2014「iOS8のコントローラーの進歩の表示」では、以下のコードがiPhoneでポップオーバーを表示できます。

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

    UINavigationController * nvc = segue.destinationViewController;
    UIPopoverPresentationController * pvc = nvc.popoverPresentationController;
    pvc.delegate = self;
}

#pragma mark == UIPopoverPresentationControllerDelegate ==
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
    return UIModalPresentationNone;
}

しかし、Xcode 6.1では、これらのコードはFullScreenプレゼンテーションを表示します...(nvc.popoverPresentationControllerはnilです)

Appleのバグではないかと思う。

2
nomadmonad

必ず実装してください IAdaptivePresentationControllerDelegate

このような:

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

フルスクリーンポップオーバーが必要ない場合

2
ader

IOS 8.3以降では、UIPopoverPresentationControllerDelegateプロトコルで次の構文を使用して、ポップアップのUIModalPresentationStyleをオーバーライドします。

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

これら2つのメソッドをWEBVIEWクラスに追加します。そして追加

-(void) prepareForSegue: (UIStoryboardSegue * ) segue sender: (id) sender {
    // Assuming you've hooked this all up in a Storyboard with a popover presentation style
    if ([segue.identifier isEqualToString: @"showPopover"]) {
        UINavigationController * destNav = segue.destinationViewController;
        pop = destNav.viewControllers.firstObject;
        // This is the important part
        UIPopoverPresentationController * popPC = destNav.popoverPresentationController;
        popPC.delegate = self;
    }
}

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