当不是模态时,展开segue不会忽略自适应弹出窗口

时间:2015-01-31 03:05:10

标签: ios objective-c ios8 unwind-segue adaptive-ui

iOS 9测试版的更新:Apple可能已针对iOS 9解决此问题。如果您针对iOS 8解决此问题,请确保它在iOS 9上也能正常运行。

在故事板中,我创建了一个popover演示文件segue,用于从按钮呈现导航和视图控制器,以及创建展开segue。

在纵向方向上,模式(全屏)演示文稿已按预期展开/解除。

在横向方向上,unwind segue也会被调用,但是popover演示文稿 not 会被自动解除。

我是否错过了挂钩的东西?我是否必须自己解雇popover演示文稿?

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
    if ([[segue identifier] isEqualToString:@"showSelectBookChapter"])
    {
        UINavigationController *navigationController = segue.destinationViewController;

        if ([navigationController.topViewController isKindOfClass:[BIBLESelectViewController class]])
        {
            BIBLESelectViewController *selectViewController = (BIBLESelectViewController *)navigationController.topViewController;
            selectViewController.initialBookChapterVerse = self.bookChapterVerse;
        }
    }
}

- (IBAction)unwindToBIBLEChapterViewController:(UIStoryboardSegue *)segue
{
    if ([segue.identifier isEqualToString:@"unwindToBIBLEChapterViewController"]) {
        if ([segue.sourceViewController isKindOfClass:[BIBLESelectViewController class]])
        {
            BIBLESelectViewController *sourceViewController = (BIBLESelectViewController *)segue.sourceViewController;
            self.bookChapterVerse = sourceViewController.selectedBookChapterVerse;
            [self.tableView reloadData];

        }
    }
}

Storyboard scenes and segues更新 在查看了gabbler的示例代码之后,我将问题缩小到popover在单视图应用程序中解除罚款,但不是在Master-Detail应用程序中。

更新2: 这是层次结构的样子(为简单起见,省略了导航控制器),回答了Luis问的问题:

  • 拆分视图控制器
    • 主视图控制器
    • 详情视图控制器
      • 章节视图控制器(模态页面表)
        • 选择视图控制器(解开章节视图控制器的有问题的弹出窗口,但不解除)

正如我在上一次更新中所提到的,我创建了一个新的主/详细模板,并直接从详细视图中的(按钮)中显示了一个弹出窗口。它不会被解雇。

4 个答案:

答案 0 :(得分:11)

我也遇到了这个问题。我从主视图控制器(UISplitViewController)以模态方式(作为表单)呈现视图控制器。这个问题只发生在iPad上(也可能是横向模式下的iPhone 6+,但我没有检查)。我最后在我的展开动作方法(使用Swift)中执行了以下操作,并且它运行良好。

if !segue.sourceViewController.isBeingDismissed() {
    segue.sourceViewController.dismissViewControllerAnimated(true, completion: nil)
}

答案 1 :(得分:4)

如果您从中嵌入导航控制器中的视图控制器中作为弹出窗口,则相应的展开将无法解除弹出窗口。

这是-[UINavigationController segueForUnwindingToViewController:fromViewController:identifier]中的错误。嵌入式导航控制器应该提供一个segue,它将解除弹出窗口但不会。然后修复将覆盖它并提供一个工作segue,我们可以从嵌入式视图控制器获取。

这是一个部分解决方案,只处理导航堆栈的顶视图控制器的展开:

@implementation MyNavigationController

- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController
                                      fromViewController:(UIViewController *)fromViewController
                                              identifier:(NSString *)identifier
{
  if (toViewController == self.topViewController && fromViewController.presentingViewController == self)
    return [toViewController segueForUnwindingToViewController:toViewController
                                            fromViewController:fromViewController
                                                    identifier:identifier];
  else
    return [super segueForUnwindingToViewController:toViewController
                                 fromViewController:fromViewController
                                         identifier:identifier];
}

@end

适用于横向/纵向iPad和横向/纵向iPhone的iOS 8。逻辑应该足够强大,可以在iOS 9上生存。

答案 2 :(得分:1)

这是/必须是popOver segue的行为,在正常情况下或者经常我们需要popOver保持在视图中,如果segue显示重要的东西是令人讨厌的,我们因为我们旋转设备而丢失了这些信息,I猜测这就是原生行为的原因。因此,如果我们想让它自动解散,我们必须通过自己的行为来实现这一点,这是有效的:

在detailViewController.m的方法- (void)viewDidLoad中添加:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
 addObserver:self selector:@selector(orientationChanged:)
 name:UIDeviceOrientationDidChangeNotification
 object:[UIDevice currentDevice]];

然后创建此方法:

- (void) orientationChanged:(NSNotification *)note{
UIDevice * device = note.object;
//CGRect rect = [[self view] frame];
switch(device.orientation)
{
    default:
        [self dismissViewControllerAnimated:YES completion:nil];
    break;    }}

你说在一个视图中发生了你想要的东西,但是当我使用popOvers时,我从未见过这种行为。

答案 3 :(得分:0)

mbeaty的解决方案很棒,但正如其他人所指出的那样,这个错误似乎已经在iOS 9中得到修复,并且它也不适用于通用设备设计。我已经调整了他的答案来处理这两种情况。这是代码:

@IBAction func yourUnwindSegue(segue: UIStoryboardSegue) {
    if #available(iOS 9, *) {
        return  // bug fixed in iOS 9, just return and let it work correctly
    }
    // do the fix for iOS 8 bug

    // access your SplitViewController somehow, this is one example
    let appDelegate  = UIApplication.sharedApplication().delegate as! AppDelegate
    let splitVC = appDelegate.window!.rootViewController as! YourSplitViewController

    // if the source isn't being dismissed and the splitView isn't
    //    collapsed (ie both windows are showing), do the hack to
    //    force it to dismiss
    if !segue.sourceViewController.isBeingDismissed() && splitVC.collapsed == false {
        segue.sourceViewController.dismissViewControllerAnimated(true, completion: nil)
    }
}

首先检查iOS 9是否正在运行,然后退出,因为bug似乎已修复。这将阻止多个视图被解雇的问题。另外,为了确保只在splitView显示两个窗口时才能进行此修复(仅在iPad和iPhone 6 Plus的横向和未来设备上进行)我添加了检查以确保它没有折叠。

我没有详尽地检查这一点,但似乎有效。也不是我的应用程序设置为iOS 7的最小值,我不知道是否存在这个错误,所以如果你支持iOS 8以下,你可能需要调查一下。