這是我最終建立的。我對它並不滿意,這就是爲什麼我直到現在才發佈它。它不會支持兩個賽段去查看具有相同類的控制器,並且它需要您自己跟蹤彈出窗口的源矩形和源視圖。但也許這對其他人來說是一個很好的起點。
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*/] ]
}];
}
你有沒有發現什麼你想達到一個更好的解決方案? –
我做過了,但並不完美。增加它作爲答案,如果你找出更好的東西,會很樂意聽到。 –