5

I have two view controllers, One and Two. I go from VC One to VC Two. On VC Two, I select some data that I store in an array. When I press the "Back" button on the navigation bar, I would like to send that array back to VC One.

What's the best way to do this?

Thanks!

user1797508
  • 292
  • 5
  • 16

3 Answers3

11

Why not set up a delegate property on your second view controller that the first can register as. Then when the information is stored to the array, it can also be passed back to it's delegate?

To implement this

At the top of your second view controllers .h file, you'll need to declare an @protocol that the first view controller can implement. A protocol is simular to an interface in other languages. It's a way of being sure an object implements certain methods, without needing to know specifically what that object is (view controller 1 in this case).

@protocol MyDataDelegate

- (void)recieveData:(NSArray *)theData

@end

and also declare a property for the delegate that the first view controller can set it's self as before it presents the second

@interface SecondViewController

@property (nonatomic, weak) id<MyDataDelegate> delegate;

Then in your first view controller .h file, implement the protocol as so

in the .h file

#import SecondViewController.h

@interface FirstViewController <MyDataDelegate>

//.....

and in the .m, implement the methods declared in the protocol

@implementation

//.... usual methods

- (void)recieveData:(NSArray *)theData {

    //Do something with data here
}

In order to set the first view controller as the delegate, you need to intercept the segue before it happens, by using a UIStoryBoardDelegate method. Add this to the first view controller

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

    //Get a handle on the view controller about be presented
    SecondViewController *secondViewController = segue.destinationViewController;

    if ([secondViewController isKindOfClass:[SecondViewController class]]) {
        secondViewController.delegate = self;
    }
}

Now you have a pointer to the first view controller from the second, and can call methods and pass back the data, by calling the following method in the second view controller

[self.delegate recieveData:theArrayData];

You could also add another method to the protocol to notify the delegate that the second view controller is being dismissed if you wanted. Or use some of the suggestions from the other answers

Sam Clewlow
  • 4,293
  • 26
  • 36
  • That sounds a really interesting approach, but I'm not sure concretely how to go about doing so. – user1797508 Nov 27 '12 at 15:34
  • updated my answer, also note that it's not possible to trigger events by pressing the back button, you'll need another confirm button or another way of deciding when to send back data before the user presses back – Sam Clewlow Nov 27 '12 at 19:30
  • In trying to implement, Xcode sent an error on: @property (nonatomic) MyDataDelegate *delegate; – user1797508 Nov 27 '12 at 20:34
  • The code is here:` @protocol selectedDocument -(void) getSelectedDocumentList:(NSMutableArray *)selectedDocumentList; @end @interface LibrarySelectorViewController : UIViewController @property (nonatomic) selectedDocument *delegate;` – user1797508 Nov 27 '12 at 20:35
  • ah sorry, my bad! I'll edit the answer, but you should change the line to `@property (nonatomic) id delegate;` – Sam Clewlow Nov 27 '12 at 20:43
  • Ahh! Now having a problem on the FirstViewController in the PrepareForSegue. The line destination.delegate=self; is throwing a "Property 'delegate' not found on object of type 'FirstViewController' – user1797508 Nov 27 '12 at 20:59
  • So the `prepareForSegue` method should be implemented inside the first viewControllers .m file. and the property declaration should be in the second view controllers .h file. Try changing the type from `UIViewController` to the class name of your second view controller. I'll edit the code above – Sam Clewlow Nov 28 '12 at 09:42
  • Very nice approach . – Uma Madhavi Feb 23 '16 at 06:04
4

If you are using iOS 6 you can use UnwindSegues to return information back down the stack.

Abizern
  • 146,289
  • 39
  • 203
  • 257
0

Probably the simplest way is by using NSNotification. In your prepareForSegue: have VC One listen for a custom notification from VC Two. When VC Two wants to send the array -- perhaps in its viewWillDisappear -- it posts that notification and passes the array as the notification object. VC One is notified, at which point is stops listening and uses the array.

Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • Notification is sometimes overkill for this. Delegation is best for one to one communication and notifications are for one to many. – Abizern Nov 28 '12 at 09:50
  • @Abizern - People create delegates too often when the relationship isn't actually about one object doing something on behalf of another...which is what the word really means. I believe that creating a protocol so that one "delegate" method can be called is worse clutter that registering for a notification. – Phillip Mills Nov 28 '12 at 12:15