ChatGPT解决这个技术问题 Extra ChatGPT

Unwind Segue not working in iOS 8

I have an app, that works fine under iOS 7, but when built for iOS 8 the unwind segues are not working.

I created a new project and added a modal (navigationcontroller with tableviewcontroller)and tried to use an unwind modal. Unfortunately it doesn't work either. The methods that are being unwind to, are in the desination view controller. The unwind segue is created through the storyboard (a Navigationbar button in the tableviewcontroller) When I tap the button, nothing happens. There is no log output and the modal does not disappear. It also only seems to affect modal segues. push/popover are unwound normally.

Has anyone had a similar problem and has an Idea how I could solve it?

I ran into this in a couple of places too - I'd been hoping it would be fixed by the time it gets to general release, but time is almost up!
You should update your accepted answer to @Stewart Hou's one as it is the only one that specifically addresses your issue. It will also help others experiencing the same problem find the right answer.

S
Stewart Hou

Apple has FIXED this bug in iOS 8.1 Temporary solutions for iOS 8.0 The unwind segue will not work only in next situation: View structure: UITabBarController -> UINagivationController -> UIViewController1 -> UIViewController2 Normally (in iOS 7, 8.1), When unwind from UIViewController2 to UIViewController1, it will call viewControllerForUnwindSegueAction in UIViewController1. However in iOS 8.0 and 8.0.x, it will call viewControllerForUnwindSegueAction in UITabBarController instead of UIViewController1, that is why unwind segue no longer working. Solution: override viewControllerForUnwindSegueAction in UITabBarController by create a custom UITabBarController and use the custom one.

For Swift

CustomTabBarController.swift

import UIKit

class CustomTabBarController: UITabBarController {

    override func viewControllerForUnwindSegueAction(action: Selector, fromViewController: UIViewController, withSender sender: AnyObject?) -> UIViewController? {
        var resultVC = self.selectedViewController?.viewControllerForUnwindSegueAction(action, fromViewController: fromViewController, withSender: sender)
        return resultVC
    }

}

For old school Objective-C

CustomTabBarController.h

#import <UIKit/UIKit.h>

@interface CustomTabBarController : UITabBarController

@end

CustomTabBarController.m

#import "CustomTabBarController.h"

@interface CustomTabBarController ()

@end

@implementation CustomTabBarController

    -(UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
    {
        return [self.selectedViewController viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender];
    }

@end

============================================================================== DO NOT USE ANY SOLUTIONS BELOW THIS POINT (they are out of date and just for reference)

Latest update on Sep 23

My new solution is pushing to a view that embedded in a navigation controller, and config that navigation controller to hide bottom bar on push(a tick box in IB). Then you will have a view looks like a modal view, the only different is the animate of pushing and popping. You can custom if you want

Updated: The solution below actually present the modal view under the tab bar, which will cause further view layout problems.

Change the segue type to Present As Popover will work only on iOS8 for iPhones, on iOS7 your app will crash.

Same here, to fix this, I set segue's presentation to current context(my app is for iphone only).

Default and full screen will not work.

https://i.stack.imgur.com/X45R7.png


Have been banging my head against the wall on this for days. This is the solution that finally worked. Thanks! Can now build in XCode 6.
All my modal segues on iPad were broken, this solved the issue for me as well.
Setting Current Context as presentation type re-enabled the unwind segues for me. However there is still some unexpected behaviours.
Hello all. My latest and greatest fix: go back to the old delegate method! I use the segue to open a popover or a modal view, and use the standard delegate method to dismiss it. All back to normal!
Is it possible that the 8.0 bug has returned in iOS 9? My unwind segue (with a tabbarcontroller) works fine on iOS 8.1, but stopped working on iOS 9...
R
Raul Rea

[UPDATE: Bug fixed on iOS 8.1 beta but you'll need it for 8.0 and 8.0.2 support]

The only way I could make my unwind segue work was by mixing Aditya's and viirus' answers.

My setup going in: [View Controller 1] > custom modal segue > [Navigation Controller] > root > [View Controller 2]

Unwind: [View Controller 2] > custom unwind segue > [View Controller 1]

Fix: Subclass the [Navigation Controller], add a property called sourceViewController and pass "self" to that property when prepare for segue is called when going from [View Controller 1] to [Navigation Controller]

In the [Navigation Controller] subclass .m override/add this two methods:

- (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
{

    if ([self.sourceViewController canPerformUnwindSegueAction:action fromViewController:fromViewController withSender:sender]) {
    return self.sourceViewController;
    }
    return [super viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender];   
}

Then I override this in that [Navigation Controller] subclass only because I have a custom unwind segue:

- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier {
   return [fromViewController segueForUnwindingToViewController:toViewController
                                          fromViewController:fromViewController
                                                  identifier:identifier];
}

The only solution that worked for me, thanks. In my case i was using a default unwind segue with similar setup.
This is now causing the unwind function to be called on iOS 8, however, it doesn't automatically dismiss the modal VC when on iOS 7 it does. If I programmatically dismiss it then on iOS 7 I get a message logged: warning attempt to dismiss from view controller while a presentation or dismiss is in progress! How are you working around that? I don't want to have to detect the OS and if iOS 8 then manually dismiss.
J
Jordan H

This is a problem with iOS 8.0, 8.0.1, and 8.0.2. It was resolved in 8.1; unwind segues are calling the appropriate method now.

Note that on iOS 8, modally presented view controllers may not be automatically dismissed when performing an unwind segue, unlike iOS 7. To ensure it's always dismissed, you may detect if it's being dismissed and if not then manually dismiss it. These inconsistencies are resolved in iOS 9.0.

With iOS 8.4 running on iPhone, all of the modally presented segues with all presentation styles do dismiss upon unwind, except Over Full Screen and Over Current Context. That's also the case for iPad, with the addition of Form Sheet and Page Sheet also not auto-dismissing. With iOS 9, all presentation styles auto dismiss on both iPhone and iPad.


Are you sure that not dismissing is intended and not dependent on this bug?
I'm not positive if that's intended or a different bug @DavideDeFranceschi, I just stated the behavior I see and how to make it work like it does on iOS 7.
That is great news that this is fixed in iOS 8.1!
In fact, unwind segues work fine when presenting a view controller modally with presentation style "Current". But as soon as you choose another presentation style, like "Over Full Screen" for example, then the unwind segue does not dismiss the view controller automatically. You have to add dismissViewController:animated: in the body of the unwind segue.
A
Aditya Wirayudha

Yep it kinda happen to me too, I think for your case you have to subclass the UINavigationController and override the following:

    - (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
    {

        for(UIViewController *vc in self.viewControllers){
            // Always use -canPerformUnwindSegueAction:fromViewController:withSender:
            // to determine if a view controller wants to handle an unwind action.
            if ([vc canPerformUnwindSegueAction:action fromViewController:fromViewController withSender:sender])
                return vc;
                }


        return [super viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender];
    }

Thanks a lot! I managed to get the segues to work, by adding a sourceViewController variable to the Navigationcontroller and setting it in the prepareForSegue call when displaying the modal. :)
Using this function in the nav controller I was hoping to unwind to, I was able to see that the specific Container View Controller I was hoping to unwind to, wasn't being called. I think that's the change we're seeing in iOS 8 - child container view controllers aren't being included in the unwind hierarchy flow
B
Bertl

Same problem here. Unwind method is not called. Only happens when

using modal segue

Presentation is anything but "current context"

NavigationController is not extended (using default from storyboard)

Also happens in IOS8 GM Seed, therefore I think we need to find a workaround. Sounds like a bug to me...

Extending UINavigationController and implementing viewControllerForUnwindSegueAction didn't help, as it is not fired. The only thing which gets fired is canPerformUnwindSegueAction() within the extended UINavigationController. Strange.


Are you sure that canPerformUnwindSegueAction returns YES? for me the viewControllerForUnwindSegueAction was always fired in the subclassed UINavigationController
P
Paul Brady

Woah there! I'm still getting user reports of getting stuck on a modal view in iOS 8.1.1 (on an iPad 3).

I'm jettisoning all this unwind from a modal view stuff. Just a good old-fashioned...

[self dismissViewControllerAnimated:NO completion:nil];

...works fine on all those various iOS 8.x.x versions.


R
Rob Zombie

It seems that both iOS 7.1 and iOS 8.1/8.2 create unwind segue from navigation controller however unwind segue is registered on a child controller inside of navigation controller.

So manually creating an unwind segue from the controller where it's registered in storyboard solves the problem.

@implementation RootNavigationController

- (UIStoryboardSegue*)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier {
    return [toViewController segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier];
}

@end

J
Jitendra Kulkarni

I encountered the same problem when unwinding to a source view controller from a destination view controller. The destination was presented through a "show" segue from the source. I was using iPhone simulator that shows iPhone 6, iOS8.3. XCode 6.3.2

The solution of subclassing NavigationViewController worked for me. Here is the swift code which is essentially swift translation of Raul's answer. I am puzzled that if Apple has fixed it in iOS8.1 per Raul, how am I getting hit by it in 8.3.

var sourceViewController: UIViewController?
override func viewControllerForUnwindSegueAction(action: Selector, fromViewController: UIViewController, withSender sender: AnyObject?) -> UIViewController? {
        if(self.sourceViewController! .canPerformUnwindSegueAction(action, fromViewController: fromViewController, withSender: sender!)){
            return self.sourceViewController
        }
        return super.viewControllerForUnwindSegueAction(action, fromViewController: fromViewController, withSender: sender)
    }

u
user3483058

I just ran into this problem, and after some digging discovered that with modal segues (at least ones with the default and fullscreen presentation modes), you can't rely on the normal unwind mechanism, but rather you have to call the presented UIViewController's dismissViewControllerAnimated method.


R
Rick

Steps to be followed:

Link the unwind segue to the button in Storyboard. Create IBAction for the button and add the below code in it: [self dismissViewControllerAnimated:NO completion:nil];

This should work for all versions.