简体   繁体   English

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

[英]Unwind segue doesn't dismiss adaptive popover presentation when not modal

Update for iOS 9 beta: Apple may have fixed this for iOS 9. If you work(ed) around this issue for iOS 8, make sure it also works correctly on iOS 9. iOS 9测试版的更新:Apple可能已针对iOS 9修复此问题。如果您针对iOS 8解决此问题,请确保它在iOS 9上也能正常运行。

In storyboard, I've created a popover presentation segue to present a navigation and view controller from a button, as well as creating an unwind segue. 在故事板中,我创建了一个popover演示文件segue,用于从按钮呈现导航和视图控制器,以及创建展开segue。

In portrait orientation, the modal (fullscreen) presentation is unwound/dismissed, as expected. 在纵向方向上,模态(全屏)演示按预期展开/解除。

In landscape orientation, the unwind segue also gets called, however the popover presentation is not automatically dismissed. 在横向方向上,展开的segue也会被调用,但是弹出窗口不会被自动解除。

Did I miss hooking something up? 我错过了挂钩的东西吗? Do I have to dismiss the popover presentation myself? 我是否必须自己解雇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];

        }
    }
}

故事板场景和segues Update: After looking at gabbler's sample code, I've narrowed the problem down to popover dismissing fine in a Single View Application, but not in a Master-Detail Application. 更新:在查看gabbler的示例代码之后,我已经将问题缩小到popover在单视图应用程序中解除罚款,但不是在Master-Detail应用程序中。

Update 2: Here's what the hierarchy looks like (omitting navigation controllers for simplicity's sake), in answer to the question Luis asked: 更新2:这是层次结构的样子(为简单起见,省略了导航控制器),回答了Luis问的问题:

  • Split view controller 拆分视图控制器
    • Master view controller 主视图控制器
    • Detail view controller 细节视图控制器
      • Chapter view controller (modal page sheet) 章节视图控制器(模态页面表)
        • Select view controller (the problematic popover that unwinds to chapter view controller, but doesn't dismiss) 选择视图控制器(解开章节视图控制器的有问题的弹出窗口,但不解除)

As I mentioned in the previous update, I created an new master/detail template, and simply presented a popover directly from (a button in) the detail view. 正如我在上一次更新中提到的,我创建了一个新的主/详细模板,并直接从详细视图中的(按钮)中显示了一个弹出窗口。 It won't dismiss. 它不会被解雇。

I ran into this problem too. 我也遇到了这个问题。 I present a View Controller modally (as a form sheet), from the Master View Controller (UISplitViewController). 我从主视图控制器(UISplitViewController)以模态方式(作为表单)呈现视图控制器。 The problem only occurred on the iPad (probably the iPhone 6+ in landscape mode too, but I didn't check it). 这个问题只发生在iPad上(也可能是横向模式下的iPhone 6+,但我没有检查)。 I ended up doing the following in my unwind action method (using Swift), and it works good. 我最后在我的展开动作方法(使用Swift)中执行了以下操作,并且它运行良好。

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

If you segue as a popover from a view controller embedded in a navigation controller, the corresponding unwind fails to dismiss the popover. 如果您嵌入在导航控制器中的视图控制器中作为弹出窗口进行切换,则相应的展开将无法解除弹出窗口。

It's a bug in -[UINavigationController segueForUnwindingToViewController:fromViewController:identifier] . 这是一个错误-[UINavigationController segueForUnwindingToViewController:fromViewController:identifier] The embedding navigation controller is supposed to supply a segue that will dismiss the popover but it doesn't. 嵌入式导航控制器应该提供一个segue,它将解除弹出窗口但不会。 The fix then is to override this and supply a working segue, which we can get from the embedded view controller. 然后修复将覆盖它并提供一个工作segue,我们可以从嵌入式视图控制器获取。

Here's a partial solution that will only handle unwinding to the top view controller of the navigation stack: 这是一个部分解决方案,只处理导航堆栈的顶视图控制器的展开:

@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

It works on iOS 8 for both landscape/portrait iPad and landscape/portrait iPhone. 它适用于iOS 8,适用于横向/纵向iPad和横向/纵向iPhone。 The logic should be robust enough to survive on iOS 9. 逻辑应足够强大,以便在iOS 9上生存。

It is/must be a behavior of the popOver segue, in normal situations or regularly we need that the popOver keeps in view, if the segue show something important is annoying that we lost that information just because we rotate the device, I guess that that is the reason of that native behavior. 这是/必须是popOver segue的行为,在正常情况下或者经常我们需要popOver保持在视图中,如果segue显示重要的东西是令人讨厌的,我们丢失了那些信息只是因为我们旋转设备,我猜那个是原生行为的原因。 So if we want for it to dismiss automaticly we have to make that behaivor by our own, this works: 因此,如果我们想让它自动解散,我们必须通过我们自己的行为,这有效:

in the method - (void)viewDidLoad in the detailViewController.m add this: 在detailViewController.m中的方法- (void)viewDidLoad中添加:

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

then create this method: 然后创建此方法:

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

You said that in a single view happens what you want, but I've never seen that behavior when I used popOvers. 你说在一个视图中发生了你想要的东西,但是当我使用popOvers时我从未见过这种行为。

mbeaty's fix is great but as others have pointed out, this bug seems to know be fixed in iOS 9 and it also doesn't work well for universal device design. mbeaty的解决方案很棒,但正如其他人所指出的那样,这个bug似乎已经在iOS 9中得到修复,并且它也不适用于通用设备设计。 I have adapted his answer to handle both situations. 我已经调整了他的答案来处理这两种情况。 Here is the code: 这是代码:

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

This first checks if iOS 9 is running and just exit as the bug seems to be fixed. 这首先检查iOS 9是否正在运行,然后退出,因为bug似乎已修复。 This will prevent the multiple views getting dismissed issue. 这将阻止多个视图被解雇的问题。 Also to make sure this fix is only done when the splitView is showing two windows (to make it happen only on iPads and iPhone 6 Plus in landscape as well as future devices) I added the check to make sure it is not collapsed. 另外,为了确保只在splitView显示两个窗口时才能进行此修复(仅在iPad和iPhone 6 Plus的横向和未来设备上进行)我添加了检查以确保它没有折叠。

I have not exhaustively check this but it seems to work. 我没有详尽地检查这一点,但它似乎工作。 Also not that my app is set for a min of iOS 7, I don't know if this bug existed then so you may need to look into that if you support below iOS 8. 也不是我的应用程序设置为iOS 7的分钟,我不知道这个错误是否存在然后你可能需要调查,如果你支持iOS 8以下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM