2014-11-01 48 views
16

我使用了新的自適應「存在酥料餅」的iOS 8的能力我在故事板做演示有線了一個簡單的SEGUE。它適用於iPhone 6 Plus,因爲它將視圖呈現爲彈出窗口,在iPhone 4上顯示爲全屏視圖(表單樣式)。的iOS 8 presentationController確定是否真的是酥料餅

問題是,當顯示爲全屏視圖,我需要添加「完成」按鈕的視圖,以便dismissViewControllerAnimated可以被調用。當它顯示爲彈出窗口時,我不想顯示「完成」按鈕。

enter image description here

我試圖尋找在兩個presentationController和popoverPresentationController的屬性,我能找到什麼,告訴我,如果它實際上是被顯示爲酥料餅。

NSLog(@"View loaded %lx", (long)self.presentationController.adaptivePresentationStyle);   // UIModalPresentationFullScreen 
NSLog(@"View loaded %lx", (long)self.presentationController.presentationStyle);     // UIModalPresentationPopover 
NSLog(@"View loaded %lx", (long)self.popoverPresentationController.adaptivePresentationStyle); // UIModalPresentationFullScreen 
NSLog(@"View loaded %lx", (long)self.popoverPresentationController.presentationStyle);   // UIModalPresentationPopover 

adaptivePresentationStyle總是返回UIModalPresentationFullScreen和presentationStyle總是返回UIModalPresentationPopover

當在UITraitCollection我沒有找到一個名爲「_UITraitNameInteractionModel」時,它實際上顯示爲酥料餅這是隻設置爲1特質期待。但是,Apple不通過popoverPresentationController的traitCollection提供對該特徵的直接訪問。

+0

您是否找到解決方案了? – Bruce 2015-08-02 07:02:21

+0

我認爲羅布格拉西的回答是最完整的。但是,蘋果應該提供一個更簡單的方法來做到這一點。 – 2015-09-27 05:35:18

+0

@TodCunningham蘋果提供了一個簡單的方法,請參閱我的答案。 – malhal 2016-03-01 13:45:01

回答

11

的最佳方式(至少有異味),我發現這樣做是使用UIPopoverPresentationControllerDelegate

•確保在UIPopoverPresentationController上使用UIPopoverPresentationControllerDelegate將呈現的視圖控制器設置爲用於管理演示文稿。我使用這樣設置這prepareForSegue:

segue.destinationViewController.popoverPresentationController.delegate = presentedVC; 

一個Storyboard•創建所呈現的視圖控制器屬性來跟蹤這種狀態:

@property (nonatomic, assign) BOOL amDisplayedInAPopover; 

•並添加以下的委託方法(或添加到您現有的委託方法):

- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController 
{ 
    // This method is only called if we are presented in a popover 
    self.amDisplayedInAPopover = YES; 
} 

•然後終於在viewWillAppear: - viewDidLoad:太早,委託準備米ethod被稱爲viewDidLoad:viewWillAppear:之間

if (self.amDisplayedInAPopover) { 
    // Hide the offending buttons in whatever manner you do so 
    self.navigationItem.leftBarButtonItem = nil; 
} 

編輯:更簡單的方法!

剛剛成立的委託(確保你presentedVC採用UIPopoverPresentationControllerDelegate):

segue.destinationViewController.popoverPresentationController.delegate = presentedVC; 

和供應的方法:

- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController 
{ 
    // This method is only called if we are presented in a popover 
    // Hide the offending buttons in whatever manner you do so 
    self.navigationItem.leftBarButtonItem = nil; 
} 
+0

如何獲取prepareForSegue中的呈現內容的引用? – Bruce 2015-08-02 07:22:07

+1

segue.destinationViewController是開始尋找的地方。注意,如果您在視圖控制器之前有一個介入的導航控制器,您認爲您正在呈現,因爲目標VC將是導航控制器。 – 2015-08-02 07:26:36

+0

這正是我的情況。我有一個介入的導航控制器,所以我最終引用我的呈現VC這樣:segue.destinationViewController.topViewController as? UIPopoverPresentationControllerDelegate,它似乎工作..它看起來是正確的? – Bruce 2015-08-02 07:52:40

2

管理您的視圖控制器的UIPresentationController通過將modalPresentationStyle設置爲UIModalPresentationPopover來顯示它。

作爲每UIViewControllerreference

presentingViewController

  • 所呈現該視圖 控制器視圖控制器。 (只讀)

modalPresentationStyle

  • UIModalPresentationPopover:在一個水平定期的環境,其中內容顯示在酥料餅視圖表現風格。背景內容變暗,在彈出窗口外點擊 ,導致彈出窗口被解除。如果您不想 想要點擊以關閉彈出窗口,則可以將一個或多個視圖分配給 UIPopoverPresentationController對象的passthroughViews屬性,您可以從 popoverPresentationController屬性中獲取該對象的passthroughViews屬性。

因此,我們可以判斷您的視圖控制器是否是酥料餅裏或通過檢查horizontalSizeClass如下模態呈現(我假定你的按鈕是UIBarButtonItem

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    if (self.presentingViewController.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) 
     self.navigationItem.leftBarButtonItem = nil; // remove the button 
} 

檢查最安全的地方這是viewWillAppear:,否則presentingViewController可能是nil

+0

你不能從水平尺寸類推導出你是否在彈出窗口中。 iPhone上的視圖控制器也具有常規的水平尺寸等級。 – 2014-11-24 20:44:20

+0

@FredA。查看WWDC 2014 Session 216 @ 4:24。 iPhone(iPhone 6Plus除外)在水平和垂直方向均具有緊湊的尺寸等級。發佈的解決方案在我的一個項目中正常工作,在該項目中,我使用「Present as Popover」自適應細節呈現popover控制器。不是爲你工作嗎? – 2014-11-25 08:56:31

+1

這可能會起作用,但它與檢查userInterfaceIdiom是否是iPad相同。此外,即使在iPhone上,您也可以強制將內容顯示在彈出窗口中。所以我認爲這個問題是關於具體檢查內容是否出現在popover中。 – 2014-11-25 09:51:00

9

我檢查是否在佈局視圖之後設置popoverPresentationController的arrowDirection。就我的目的而言,這種方法運作良好,涵蓋較小的屏蔽設備上的彈出式菜單。

override func viewWillAppear(animated: Bool) { 
    super.viewWillAppear(animated) 

    if (popoverPresentationController?.arrowDirection != UIPopoverArrowDirection.Unknown) { 
     // This view controller is running in a popover 
     NSLog("I'm running in a Popover") 
    } 
} 
+0

自從回答這個問題以來,你找到了更好的方法嗎? – SAHM 2015-03-16 00:02:31

+0

對我來說不適用於Xcode 6.4 – Bruce 2015-08-02 07:01:25

2

如何

if (self.modalPresentationStyle == UIModalPresentationPopover) 

它的工作對我來說

2

實現這一官方的辦法就是先取下完成按鈕從你的視圖控制器,第二,當適應緊湊嵌入您的視圖控制器在導航控制器,添加完成按鈕作爲導航項目:

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

Full Tutorial

Screenshots

3

我測試了在這個崗位提出的所有解決方案。對不起,在所有情況下都無法正常工作。例如在iPad中,分隔視圖的演示樣式可以在拖動分隔視圖的同時更改,因此我們需要特定的通知。 研究的幾個小時後,我發現蘋果樣品(SWIFT)在溶液: https://developer.apple.com/library/ios/samplecode/AdaptivePhotos/Introduction/Intro.html#//apple_ref/doc/uid/TP40014636

以下是在OBJ-c中的相同的溶液。

先在prepareForSegue函數中設置popoverPresentationController委託。它也可以在MyViewController「init」中設置,但不能在「viewDidLoad」中設置(因爲在viewDidLoad之前調用了第一個willPresentWithAdaptiveStyle)。

MyViewController *controller = [segue destinationViewController]; 
     controller.popoverPresentationController.delegate = (MyViewController *)controller; 

現在MyViewController對象每次改變演示風格,包括第一次呈現,都會收到此通知。下面是示例實現,顯示/隱藏navigationController「關閉」按鈕:

- (void)presentationController:(UIPresentationController *)presentationController 
    willPresentWithAdaptiveStyle:(UIModalPresentationStyle)style 
     transitionCoordinator:(nullable id<UIViewControllerTransitionCoordinator>)transitionCoordinator { 
    if (style == UIModalPresentationNone) { 
     // style set in storyboard not changed (popover), hide close button 
     self.topViewController.navigationItem.leftBarButtonItem = nil; 
    } else { 
     // style changed by iOS (to fullscreen or page sheet), show close button 
     UIBarButtonItem *closeButton = 
      [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeAction)]; 
     self.topViewController.navigationItem.leftBarButtonItem = closeButton; 
    } 
} 

- (void)closeAction { 
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 
} 
2

解決方案與多任務

分配呈現控制器作爲酥料餅的委託

... 
controller.popoverPresentationController.delegate = controller; 
[self presentViewController:controller animated:YES completion:nil]; 

然後工作,在控制器中執行代表方法:

- (void)presentationController:(UIPresentationController *)presentationController willPresentWithAdaptiveStyle:(UIModalPresentationStyle)style transitionCoordinator:(id<UIViewControllerTransitionCoordinator>)transitionCoordinator 
{ 
    if (style != UIModalPresentationNone) 
    { 
     // Exited popover mode 
     self.navigationItem.leftBarButtonItem = button; 
    } 
} 

- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController 
{ 
    // Entered popover mode 
    self.navigationItem.leftBarButtonItem = nil; 
} 
0

我的棘手的解決方案,完美的作品。

PopoverViewControllerviewDidLoad

if (self.view.superview!.bounds != UIScreen.main.bounds) { 
    print("This is a popover!") 
} 

的想法很簡單,A酥料餅的看法大小決不等於設備的屏幕大小,除非它不是一個酥料餅。

+0

這對我來說非常合適,但必須在viewDidAppear中執行檢查。 – 2017-12-14 10:54:21