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?
Solution 1:
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.
Solution 2:
[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];
}