11

I came across an interesting problem, i have main ViewController let's call him MainVC with navigationController and i am doing performSegueWithIdentifier from him to Mine second ViewController let's call him SecVC. so when i am trying to do the popViewControllerAnimated i want to pass some data from the SecVC to the MainVc.. i know i can do it with appDelegate Param or with singletons class but my question is : can i do it with more Elegant solution? like i use prepareForSegue and use local parmeters..

Thank you...

Sosily
  • 706
  • 1
  • 10
  • 26
  • As per my knowledge it's not possible. you have to tak either golabla variable to store your data or store it in user defaults. – Niru Mukund Shah Nov 22 '12 at 09:50
  • i will .. i want to try without :( – Sosily Nov 22 '12 at 10:54
  • here is a TRUE way to use the delegate with popViewControllerAnimated in Swift!: http://stackoverflow.com/questions/39692791/swift-how-to-call-delegate-with-popviewcontroller – David Seek Sep 26 '16 at 11:31

5 Answers5

18

The best way to do it is by using a delegate.

//SecVCDelegate.h

#import <Foundation/Foundation.h>

@protocol SecVSDelegate <NSObject>

@optional
- (void)secVCDidDismisWithData:(NSObject*)data;
@end

//SecVC.h

#import <UIKit/UIKit.h>
#import "SecVSDelegate.h"

@interface SecVC : UIViewController

/** Returns the delegate */
@property (nonatomic, assign)   id<SecVSDelegate> delegate;

@end

//SecVC.M

...

- (void) dealloc
{
...
delegate = nil
...
}

When ever you popViewControllerAnimated, right after it (or before it) you do this

if(_delegate && [_delegate respondsToSelector:@selector(secVCDidDismisWithData:)])
{
[_delegate secVCDidDismisWithData:myDataObject];
}

And in the MainVC you must be certain that you implement the delegate function //MainVC.m

- (void)secVCDidDismisWithData
{
//do whatever you want with the data
}

To avoid any warnings you must tell that the MainVC class implements the delegate like this:

//MainVC.h

#import "SecVCDelegate.h"
...
@interface MainVC : UIViewController <SecVCDelegate>
...
secVCInstance.delegate = self;
[self.navigationController pushViewController:secVCInstance]; 
...
Saliom
  • 1,050
  • 9
  • 15
16

While I agree that the best option is to use Delegate, but still if any one is looking for something different, he can use NSNotificationCenter as an alternative.

In viewDidLoad of MainVC:

- (void)viewDidLoad
{

    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(recvData:)
                                             name:@"SecVCPopped"
                                           object:nil];
}

And add method recvData in MainVC.m

- (void) recvData:(NSNotification *) notification
{

    NSDictionary* userInfo = notification.userInfo;
    int messageTotal = [[userInfo objectForKey:@"total"] intValue];
    NSLog (@"Successfully received data from notification! %i", messageTotal);
}

Now in SecVC, before popping, add this line

NSMutableDictionary* userInfo = [NSMutableDictionary dictionary];
[userInfo setObject:[NSNumber numberWithInt:messageTotal] forKey:@"total"];

NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:@"SecVCPopped" object:self userInfo:userInfo];
Boggarapu
  • 333
  • 2
  • 7
  • 15
Atif Alvi
  • 498
  • 4
  • 12
1

I would do it in one of the following ways, but I'm not sure if it's elegant enough...

  1. In SecVC, add an @property MainVC *mainVC; Use [self.mainVC setSomeValue:...]; before calling [self.navigationController popViewControllerAnimated:...];

  2. Use [self.navigationController viewControllers]; to find out the MainVC *mainVC, and call [mainVC setSomeValue:...]; before the line of code that pop the ViewController.

Is this what you want?

Darshan Kunjadiya
  • 3,323
  • 1
  • 29
  • 31
John
  • 2,672
  • 2
  • 23
  • 29
1

I simply set up a protocol in the view being dismissed (example in Swift):

 protocol ExampleTableViewControllerDismissDelegate {
    func didDismiss(withData: Any)
}

var delegate: SearchableTableViewControllerDismissDelegate?

You can then call this when you dismiss/pop your view like this

self.navigationController?.popViewController(animated: true)
delegate?.didDismiss(withData: Any)

Then in the view being dismissed to (the parent in the hierarchy), we can conform to the delegate and essentially get a callback with the data after the view has been dismissed.

//MARK: ExampleTableViewControllerDismissDelegate

func didDismiss(withData: Any) {
    //do some funky stuff
}

And don't forget to subscribe to the delegate in the parent view by using

viewController.delegate = self
Harry Bloom
  • 2,359
  • 25
  • 17
0

There is another way to pass data between views including popViewControllerAnimated and it's with a global var instance, so If you modify that Var in your detail view and after do the popViewControllerAnimated, you can call the new data in the viewWillAppear method.

The first step is declare the Global var in main.h

NSMutableArray * layerList;

And now you have to call it in detail view.

SecondView.m

extern NSString *layerList;

SecondView.h

-(void)back{
    layerList = @"Value to send";
    [self.navigationController popViewControllerAnimated:YES];
}

Now you can use the information in the Master View after detect the pop action.

FirstView.m

extern NSString *layerList;

FirstView.h

-(void)viewWillAppear:(BOOL)animated{
   NSLog(@"This is what I received: %@",layerList);
}
lojals
  • 981
  • 10
  • 19