25

I have created a simple unwind segue using the storyboard tools. I have created the following event handler in the view I want to unwind to:

-(IBAction)quitQuiz:(UIStoryboardSegue *)segue {
    NSLog(@"SEGUE unwind");
}

This fires correctly and unwinds the segue (the message gets logged).

When the user quits the quiz I would like to pass some data back and have been struggling with how to achieve this. Can anyone advise?

Mark Tyers
  • 2,961
  • 4
  • 29
  • 52
  • Hi, did you get to solve this? I am also looking for the solution. Tq – dan Dec 03 '12 at 04:22
  • 1
    Jeff's answer _is_ the solution. `YourViewController *yourVC = [segue sourceViewController];` inside your unwind method and then you can access your outlets/fields on that VC object. – Voicu Mar 26 '13 at 06:41
  • 1
    It works and everything, but it's a shame that the only mechanism for an unwind handler (the destination `UIViewController`) to pick up information from the unwind initiator is through the public interface of the `UIViewController` that is being unwound from. It would be nice if the `UIStoryboardSegue` also provided a way to know the `sender` that initiated the unwind. I think that in many cases this might be a better way to provide information to the unwind handler. – Benjohn Dec 31 '14 at 16:09

6 Answers6

35

Thanks Jeff. After watching WWDC video 407 I have a clear solution.

In the view controller that is the target of the unwind you should create a method that takes a single UIStoryboardSegue parameter and returns an IBAction. The UIStoryboardSegue has a method to return the source view controller! Here is the example taken from the video (credit to Apple).

- (IBAction)done:(UIStoryboardSegue *)segue {
    ConfirmationViewController *cc = [segue sourceViewController];
    [self setAccountInfo:[cc accountInfo]];
    [self setShowingSuccessView:YES];
}
Mark Tyers
  • 351
  • 2
  • 2
  • Nice code, just to clarify: ConfirmationViewController is the view controller we unwinded from, and this method exists in the view controller we want to unwind to. – fullmoon Mar 17 '15 at 14:04
  • 1
    For reference, here is a link to the aforementioned WWDC video. The relevant part starts at around the 37 min mark: https://developer.apple.com/videos/play/wwdc2012-407/ – Oz Solomon Jan 14 '16 at 21:33
11

Getting data back from an unwind segue is explained very nicely in this apple talk, second half of the presentation (edit: starts from 37:20)

In particular, in an unwind segue the [segue sourceViewController] is the still active view controller from which the unwind event originated, so just access your properties as usual.

mmmmmm
  • 32,227
  • 27
  • 88
  • 117
Jeff
  • 6,646
  • 5
  • 27
  • 33
5

Add the function prepareForSeque in the controller being closed.

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

This function is called before the unwind segue is called (in your example you called it quitQuiz). As you can see, it also has a sender parameter so that you can find out who called the unwind and collect the relevant data accordingly.

For example of the WWDC 407 video, if you clicked the reset button you would not set the accountInfo and if you clicked the done button you would.

Yasmin Tiomkin
  • 282
  • 1
  • 5
  • 14
1

Set up a delegate and inform your source view controller about quitting the quiz and send back the data. Don't forget to set the source view controller as the delegate of the destination view controller.

// DestinationViewController.h
@protocol DestingationDelegate;
@interface 
...
@property (assign) id<DestinationDelegate> delegate;
...
@end

@protocol DestinationDelegate
-(void)didQuitQuiz:(NSDictionary*)infoDict;
@end

// DestinationViewController.m
-(IBAction)quitQuiz:(UIStoryboardSegue *)segue {
  NSLog(@"SEGUE unwind");
  if (self.delegate) [self.delegate didQuitQuiz:infoDict];
}


// SourceViewController.h
#import DestinationViewController.h
@interface SourceViewController : ViewController <DestinationDelegate>
....

// SourceViewController.m
-(void)didQuitQuiz:(NSDictionary *)infoDict {
    if (infoDict) {
       // do something with the data
    }
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
   ...
   destinationViewController.delegate = self;
}
Mundi
  • 79,884
  • 17
  • 117
  • 140
  • 1
    Protocols are great, but iOS6 makes life much easier with unwind segues, which is what the poster is asking about. – Jeff Oct 26 '12 at 16:03
1

Yes,
For that, you will need to make properties, which holds your data to be sent from another view controller:

    - (IBAction)unwindSelectFriendsVC:(UIStoryboardSegue *)segue
    {
        if ([segue.sourceViewController isKindOfClass:[ChildVC class]]) {

            ChildVC *child = (ChildVC *) segue.sourceViewController;

            //here we are passing array of selected friends by arrSelectedFriends property
            self.arrFriendList = child.arrSelectedFriends;
            [self.tableView reloadData];
        }
    }
Nitesh Borad
  • 4,583
  • 36
  • 51
0

Passing data between view controllers is frequently accomplished using protocols. Here's an example:

In your quiz view controller header, declare a similar protocol definition:

@protocol JBQuizViewControllerDelegate <NSObject>

@required
- (void)quizController:(id)controller didQuitWithState:(NSString *)state;

@end

In your presenting view controller's prepareForSeque: method, wire up the delegate:

JBQuizViewController *destination = (JBQuizViewController *)segue.destinationViewController;
destination.delegate = self;

Then, in your presenting view controller, handle the delegate protocol's quizController:didQuitWithState: method.

Finally, once the user quits your quiz, you should notify the delegate using the protocol, passing in the state or whatever data you want to expose.

Jesse Bunch
  • 6,651
  • 4
  • 36
  • 59