Unwind segue doesn't reject responsive popover presentation when not modal

Update for iOS 9 beta: Apple may have fixed this for iOS 9. If you are working on this issue for iOS 8, make sure that it also works correctly on iOS 9.

In the storyboard, I created a segue presentation to present the navigation and view controller with a button, as well as create a spinning segment.

In portrait orientation, a modal (full-screen) view is unwound / rejected as expected.

In landscape orientation, a challenge is played, but the popover presentation does not automatically decline.

Did I miss something? Should I decline a popover presentation?

- (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 Update: After looking at the code for the gabbur example, I narrowed down the problem before the question of dismissal surfaced in the Single View application, but not in the Master Details application.

Update 2: This is what the hierarchy looks like (lowering the navigation controllers for simplicity), answering a question from Louis, he asked:

  • Split image controller
    • Master view controller
    • Detail view controller
      • Chapter view controller (modal page sheet)
        • Select a view controller (a problematic popover that deploys to the chapter controller but doesn't miss it)

As I mentioned in the previous update, I created a new master / detail template and simply presented a popover directly from (on the button) the detailed view. This will not be rejected.

+6
source share
4 answers

I ran into this problem. I present the View Controller modally (as a form sheet), from the Master View Controller (UISplitViewController). The problem arose only on the iPad (perhaps the iPhone 6+ in landscape mode too, but I did not check it). I ended up doing the following in my recovery method (using Swift) and it works well.

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

If you switch as a popover from the view controller built into the navigation controller, the corresponding unwinding will not remove the popover.

This is an error in -[UINavigationController segueForUnwindingToViewController:fromViewController:identifier] . The inline navigation controller is supposed to supply a segment that will reject the popover, but that is not the case. Then the fix is ​​to override this and provide a working segment that we can get from the built-in view controller.

Here's a partial solution that will only handle unwinding the top-level controller in 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 landscape / portrait iPad and landscape / portrait iPhone. The logic must be robust enough to survive on iOS 9.

+4
source

This / should be the behavior of popOver segue, in normal situations or regularly we need popOver to keep it in sight, if segue shows something important, it’s annoying that we lost this information only because we rotate the device, I guess that this is the reason for this behavior. Therefore, if we want him to quit automatically, we must make this behavior on our own, this works:

in the method - (void)viewDidLoad in detailViewController.m add this:

 [[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 one view what you want happens, but I never saw this behavior when I used popOvers.

+1
source

The mbeaty fix is ​​great, but as others have noted, this bug seems to be fixed in iOS 9, and it also doesn't work very well for the device’s universal design. I adapted his answer to deal with 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 working, and just exit as the error seems to be fixed. This will prevent multiple viewing problems. Also, to make sure that this correction is performed only when splitView displays two windows (so that this only happens on the iPad and iPhone 6 Plus in landscape, as well as on future devices), I added a check to make sure that it did not crash.

I am not exhaustively checking this, but it seems to work. It’s also not that my application is configured for a minimum of iOS 7, I don’t know if this error existed, so you may need to examine this if you support below iOS 8.

0
source

Source: https://habr.com/ru/post/981796/


All Articles