簡體   English   中英

如何知道視圖控制器是作為彈出窗口還是模態顯示?

[英]How to know if a view controller will be presented as a popover or modal?

在呈現視圖控制器之前,我將modalPresentationStyle屬性設置為UIModalPresentationPopover 當在具有常規水平尺寸類(iPad和iPhone 6+在橫向上)的設備上運行時,以及在其他設備上作為模態/全屏運行時,這將使視圖控制器呈現為彈出窗口。 也可以通過重寫adaptivePresentationStyleForPresentationController來覆蓋此行為,以便視圖控制器在所有設備上顯示為彈出窗口。

我想知道在提供視圖控制器之后是否有可能知道它是否作為彈出窗口呈現? 只是查看size類不會這樣做,因為視圖控制器可能會覆蓋adaptivePresentationStyleForPresentationController

顯而易見的答案是,作為程序員,我應該知道我是否覆蓋了adaptivePresentationStyleForPresentationController ,但我想編寫一個函數,可以通過傳入視圖控制器或UIPopoverPresentationController (或任何視圖控制器)在運行時為任何視圖控制器確定需要的其他對象)作為參數。

這是一些呈現視圖控制器的代碼:

navigationController = (UINavigationController *)[MVSStore sharedInstance].addViewController;
navigationController.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:navigationController animated:YES completion:^{}];

UIPopoverPresentationController *popoverController = navigationController.popoverPresentationController;
popoverController.sourceView = self.view;
popoverController.sourceRect = CGRectMake(20, 20, 20, 20); // Just a dummy
popoverController.permittedArrowDirections = UIPopoverArrowDirectionAny;

這是檢測視圖控制器是否顯示為彈出窗口的當前代碼。 但如上所述,它只是查看尺寸類,它不適用於所有情況。

+ (BOOL)willPresentTruePopover:(id<UITraitEnvironment>)vc {
    return ([vc traitCollection].horizontalSizeClass == UIUserInterfaceSizeClassRegular);
}

我在UIViewControllerUIPopoverPresentationController (或其他任何地方)中找不到任何屬性或函數,它們可以立即給我這些信息,但也許我錯過了什么?

你說你試圖這樣做來刪除取消/完成按鈕。 相反,只在需要時添加按鈕。

實現此功能的官方方法是首先從視圖控制器中刪除“完成”按鈕,然后在適應緊湊的視圖控制器嵌入導航控制器時,現在將完成按鈕添加為導航項:

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

func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
    let navigationController = UINavigationController(rootViewController: controller.presentedViewController)
    let btnDone = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismiss")
    navigationController.topViewController.navigationItem.rightBarButtonItem = btnDone
    return navigationController
}

func dismiss() {
    self.dismissViewControllerAnimated(true, completion: nil)
}

完整教程

截圖

我正以同樣的方式攻擊它,因為我在Interface Builder中設置了Done按鈕及其目標動作。 為了刪除它,我正在測試popoverPresentationController!= nil。 在我的測試設備(運行iOS 10的iPhone 5)上,此測試在運行iOS 11的iPad Pro上執行時成功忽略了iPhone。在運行iOS 11的iPhone 8上測試時遇到了問題。在iOS 11中出現了即使以模態方式呈現視圖,popoverPresentationController現在也已實例化。 因此,我只是測試呈現視圖控制器的水平尺寸類。 不確定這是否是正確的方法,但它適用於我,因為我找不到任何方法讓popoverPresentationController告訴我它實際上是模態呈現。

    weak var ppcDelegate: UIPopoverPresentationControllerDelegate?

...

    if popoverPresentationController != nil && 
        popoverPresentationController!.presentingViewController.traitCollection.horizontalSizeClass == .regular {

        navigationItem.rightBarButtonItem = nil
        popoverPresentationController?.delegate = ppcDelegate
    }

使用UIAdaptivePresentationControllerDelegate方法presentationController:willPresentWithAdaptiveStyle:transitionCoordinator: . 要在其他時間查詢表示樣式,請向表示控制器詢問其adaptivePresentationStyleForTraitCollection: ,傳遞當前特征。 這些方法已在iOS 8.3中添加, 尚未記錄

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM