1

I have an unwind segue that was working fine until I upgraded to iOS 9/XCode 7.

Here's a screenshot of the Storyboard config for the unwind segue: enter image description here

The unwind segue is triggered off of pushing a "Done" button in the UINavigationController. I intercept that action by overriding the canPerformUnwindSegueAction in a UITableViewController contained in the UINavigationController. I do this to validate data. If the data is incomplete I return YES to prevent the segue from unwinding completely.

The segue actually does unwind to the correct terminated method (in the NotificationsViewController); canPerformUnwindSegueAction just never gets called for some reason.

I've tried:

  1. Deleting and adding the unwind segue in the Storyboard.
  2. Overriding UITableViewController with my own custom ViewController that includes the canPerformUnwindSegueAction. (along the lines of this post Unwind Segue not working in iOS 8)
  3. Same as #2 overriding allowedChildViewControllersForUnwindingFromSource. (allowedChildViewControllersForUnwindingFromSource doesn't get called on the original UITableViewController either)
  4. Retargeting iOS 8.2 (the last working version) but that doesn't work either. When upgrading to iOS 9 I noticed that Xcode made over 80 changes to the .storyboard file...maybe something broke there?

Here's a backtrace that shows what happens when the "Done" button is pushed:

*** First throw call stack:
(
    0   CoreFoundation                      __exceptionPreprocess + 165
    1   libobjc.A.dylib                     objc_exception_throw + 48
    2   CoreFoundation                      -[__NSDictionaryM setObject:forKey:] + 1042
    3   Autodar                             -[Notification JSONDictionary] + 608
    4   Autodar                             -[RESTClient createNotification:withCompletionBlock:] + 290
    5   Autodar                             -[NotificationsViewController createBackendNotification:atIndex:] + 247
    6   Autodar                             -[NotificationsViewController unwindFromDone:] + 705
    7   UIKit                               -[UIStoryboardUnwindSegueTemplate _performWithDestinationViewController:sender:] + 214
    8   UIKit                               -[UIStoryboardUnwindSegueTemplate _perform:] + 86
    9   UIKit                               -[UIStoryboardSegueTemplate perform:] + 156
    10  UIKit                               -[UIApplication sendAction:to:from:forEvent:] + 92
    11  UIKit                               -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 152
    12  UIKit                               -[UIApplication sendAction:to:from:forEvent:] + 92
    13  UIKit                               -[UIControl sendAction:to:forEvent:] + 67
    14  UIKit                               -[UIControl _sendActionsForEvents:withEvent:] + 327
    15  UIKit                               -[UIControl _sendActionsForEvents:withEvent:] + 706
    16  UIKit                               -[UIControl touchesEnded:withEvent:] + 601
    17  UIKit                               -[UIWindow _sendTouchesForEvent:] + 835

Here's where I override canPeformUnwindSegueAction in my UITableViewController:

// Respond to "Done" button being pushed
// Return:
//   YES: to stop unwind and display popover for validation message
//   NO:  to unwind back to NotificationsViewController
- (BOOL)canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender {
  // return YES if data is incorrect
  return NO;
}

I'm stumped. Any ideas as to what I could do to further diagnose or resolve this would be greatly appreciated!

Community
  • 1
  • 1
Sly
  • 703
  • 12
  • 36
  • 1
    what is the exception message? – Reinier Melian Jun 13 '16 at 16:48
  • @ReinierMelian - `*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** setObjectForKey: object cannot be nil (key: search_min_year)'` The exception is a result of the fact that validation wasn't performed and the ViewController where the unwind segue terminates attempts to save a nil value. (unrelated to the unwind segue) – Sly Jun 13 '16 at 20:34
  • so you find the error ;) nice! – Reinier Melian Jun 13 '16 at 20:40
  • i think your problem is not related to segue its crashing due to `RESTClient` dictionary which you are setting as `nil` so its crashing as mention in above crash log its clearly showing that its due to `nil` value assigning in `NSDictionary` – CodeChanger Jun 21 '16 at 06:38

3 Answers3

0

Looks like the thing you want to rewind from is presented from the top of the navigation controller, right? That takes the navigation controller out of the responder chain, therefore the segue callbacks never make it to controllers in the stack. At least, I had a similar problem a while back with trying to provide a custom segue from downstack, and that was the explanation I found.

The solution to my circumstance was to push the presented sheet into the navigation controller instead of presenting it. Then everything went exactly as expected. So if that is indeed a presented sheet, try pushing instead of presenting and see if that sorts you.

Alex Curylo
  • 4,610
  • 1
  • 23
  • 35
  • thanks for the idea. I tried this by selecting the modal segue (in the storyboard) that takes me from the NotificationsViewController to the DetailViewController and changing the "Kind" setting from "Modal" to "Push" in the Attributes Inspector (Storyboard). Unfortunately I get the same result. (am I doing what you're talking about?) – Sly Jun 20 '16 at 14:57
  • Yep, that's exactly what I was suggesting. Guess you have a different problem :L – Alex Curylo Jun 20 '16 at 19:00
0

The default implementation of this method returns YES when the current view controller implements the action method and is not the same view controller as the one in the fromViewController parameter.

So it seems you implement this method in the same ViewController as fromViewController

wj2061
  • 6,201
  • 1
  • 28
  • 60
  • you're right. I've confirmed this by adding the canPerformUnwindSegueAction callback to my NotificationsViewController. (which also implements the unwindFromDone: method) fromViewController is set to DetailViewController. The question is: how do I configure the unwind segue from the Storyboard (or other code) to get it to treat the fromViewController as the UINavigationController? – Sly Jun 20 '16 at 15:46
0

I was able to resolve this by using the shouldPerformSegueWithIdentifier callback instead of canPerformUnwindSegueAction.

This post How to do something before unwind segue action? alludes to using this method.

From a storyboard perspective, I didn't need to do anything differently other than to add an identifier to the unwind segue.

I don't know why canPerformUnwindSegueAction was getting called previously in iOS8.x and stopped in iOS9.x, but hopefully this can help others as well.

Community
  • 1
  • 1
Sly
  • 703
  • 12
  • 36