2015-08-28 61 views
7

在我的應用程序中,在iPad上有某些視圖控制器(或者更具體地說,是一個常規的水平尺寸類),它將它們呈現爲彈窗是有意義的,但在iPhone(或緊湊的水平尺寸類)上它是有意義的將它們推到導航堆棧上。有沒有一種優雅的方式來支持這一點?默認情況下,如果我使用「Present as Popover」,那麼它將在iPhone上以模態方式顯示,這不是我想要的。如何創建一個將在iPad上使用彈出窗口並將其推入iPhone上的導航堆棧的segue?

我找到了一種方法來獲得我想要的行爲,但它很醜並且似乎很容易出錯。我根據目前所處的大小選擇兩種不同的階段。爲了支持iOS 9多任務處理,我實現了[UIViewController willTransitionToTraitCollection:withTransitionCoordinator]並手動將視圖控制器在popover和導航控制器之間移動(這部分看起來特別容易出錯) 。

似乎應該有一些簡單的方法來實現自定義segue來處理這個問題,或者某種自定義的自適應表示控制器,但我一直無法圍繞它來包裹我的頭。有沒有人有過這樣的成功?

+1

你有沒有發現什麼你想達到一個更好的解決方案? –

+0

我做過了,但並不完美。增加它作爲答案,如果你找出更好的東西,會很樂意聽到。 –

回答

1

據對我來說,這是最簡單的方法,

步驟1:創建從一個控制器配備了兩個塞格斯到另一個。
第2步:設置一個賽格瑞的SEGUE屬性的另一
步驟3推,酥料餅:現在叫執行SEGUE根據您的要求,ieiPad或iPhone

這裏是a sample code

示例代碼注意:將bool條件更改爲false以檢查didSelectRowAtIndexPath中的另一個條件。

+0

是的,這就是我現在正在做的。但是在嘗試實現iOS 9多任務時,它變得特別混亂。我希望找到更優雅的方法。 –

+0

好的,這是我認爲的方法。 –

1

這是我最終建立的。我對它並不滿意,這就是爲什麼我直到現在才發佈它。它不會支持兩個賽段去查看具有相同類的控制器,並且它需要您自己跟蹤彈出窗口的源矩形和源視圖。但也許這對其他人來說是一個很好的起點。

PushPopoverSegue.swift

import UIKit 

class PushPopoverSegue: UIStoryboardSegue { 

    var sourceBarButtonItem: UIBarButtonItem! 
    var permittedArrowDirections: UIPopoverArrowDirection = .Any 

    override func perform() { 
     assert(self.sourceViewController.navigationController != nil) 
     assert(self.sourceBarButtonItem != nil) 

     if self.sourceViewController.traitCollection.horizontalSizeClass == .Compact { 
      self.sourceViewController.navigationController!.pushViewController(self.destinationViewController, animated: true) 
     } 
     else { 
      let navigationController = UINavigationController(rootViewController: self.destinationViewController) 
      let popover = UIPopoverController(contentViewController: navigationController) 
      popover.presentPopoverFromBarButtonItem(self.sourceBarButtonItem, permittedArrowDirections: self.permittedArrowDirections, animated: true) 
     } 
    } 

} 

的UIViewController + PushPopoverTransition.h

#import <UIKit/UIKit.h> 

@interface UIViewController (PushPopoverTransition) 

- (void) transitionPushPopoversToHorizontalSizeClass: (UIUserInterfaceSizeClass) sizeClass withMapping: (NSDictionary*) mapping; 

@end 

的UIViewController + PushPopoverTransition.m

#import "UIViewController+PushPopoverTransition.h" 

@implementation UIViewController (PushPopoverTransition) 

- (void) transitionPushPopoversToHorizontalSizeClass: (UIUserInterfaceSizeClass) sizeClass withMapping: (NSDictionary*) mapping 
{ 
    if (sizeClass == UIUserInterfaceSizeClassCompact) 
    { 
     if (self.presentedViewController == nil) 
      return; 

     NSParameterAssert([self.presentedViewController isKindOfClass:[UINavigationController class]]); 
     UINavigationController* navigationController = (UINavigationController*) self.presentedViewController; 
     NSArray* viewControllers = navigationController.viewControllers; 
     UIViewController* topOfStack = viewControllers[0]; 

     if ([mapping.allKeys containsObject:NSStringFromClass([topOfStack class]) ]) 
     { 
      [self.presentedViewController dismissViewControllerAnimated:NO completion:^{ 
       for (UIViewController* viewController in viewControllers) 
        [self.navigationController pushViewController:viewController animated:NO]; 
      }]; 
     } 
    } 
    else if (sizeClass == UIUserInterfaceSizeClassRegular) 
    { 
     NSUInteger indexOfSelf = [self.navigationController.viewControllers indexOfObject:self]; 

     if (indexOfSelf < self.navigationController.viewControllers.count - 1) 
     { 
      UIViewController* topOfStack = self.navigationController.viewControllers[indexOfSelf + 1]; 
      if ([mapping.allKeys containsObject:NSStringFromClass([topOfStack class])]) 
      { 
       NSArray* poppedControllers = [self.navigationController popToViewController:self animated:NO]; 
       UINavigationController* navigationController = [[UINavigationController alloc] init]; 
       navigationController.modalPresentationStyle = UIModalPresentationPopover; 
       navigationController.viewControllers = poppedControllers; 

       id popoverSource = mapping[NSStringFromClass([topOfStack class])]; 
       if ([popoverSource isKindOfClass:[UIBarButtonItem class]]) 
       { 
        navigationController.popoverPresentationController.barButtonItem = popoverSource; 
       } 
       else if ([popoverSource isKindOfClass:[NSArray class]]) 
       { 
        NSArray* popoverSourceArray = (NSArray*) popoverSource; 
        NSParameterAssert(popoverSourceArray.count == 2); 
        UIView* sourceView = popoverSourceArray[0]; 
        CGRect sourceRect = [(NSValue*) popoverSourceArray[1] CGRectValue]; 
        navigationController.popoverPresentationController.sourceView = sourceView; 
        navigationController.popoverPresentationController.sourceRect = sourceRect; 
       } 

       [self presentViewController:navigationController animated:NO completion:nil]; 
      } 
     } 
    } 
} 

@end 

示例用法

在界面構建器中創建一個segue,並將其「Kind」設置爲Custom,將其「Class」設置爲PushPopoverSegue

ViewController.m

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    ((PushPopoverSegue*) segue).sourceView = /* source view */; 
    ((PushPopoverSegue*) segue).sourceRect = /* source rect */; 
} 

-(void) willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator 
{ 
    if (newCollection.horizontalSizeClass == UIUserInterfaceSizeClassUnspecified) 
     return; 

    [self transitionPushPopoversToHorizontalSizeClass:newCollection.horizontalSizeClass withMapping:@{ 
     @"MyDestinationViewController": @[ /* source view */, 
             [NSValue valueWithCGRect:/* source rect*/] ] 
    }]; 
} 
+0

你有沒有找到更好的或者你還在使用這個解決方案? – SAHM

+1

仍在使用它。它仍然在爲我工作,所以我沒有太多理由回到這裏。 –

+0

謝謝。我會試一試。你知道UIPopoverController在iOS 9中被棄用嗎? – SAHM

相關問題