'it possible to Pass Data with popViewControllerAnimated?

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...



Solution 1:[1]

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]; 
...

Solution 2:[2]

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];

Solution 3:[3]

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?

Solution 4:[4]

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

Solution 5:[5]

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);
}

Solution 6:[6]

You can pass data back using delegate

  1. Create protocol in ChildViewController

  2. Create delegate variable in ChildViewController

  3. Extend ChildViewController protocol in MainViewController

  4. Give reference to ChildViewController of MainViewController when navigate

  5. Define delegate Method in MainViewController

  6. Then you can call delegate method from ChildViewController

Example

In ChildViewController: Write code below...

protocol ChildViewControllerDelegate {
 func childViewControllerResponse(parameter)
}

class ChildViewController:UIViewController {
var delegate: ChildViewControllerDelegate?
 ....
}

In MainViewController

//extend `delegate`
class MainViewController:UIViewController,ChildViewControllerDelegate {
// Define Delegate Method

func childViewControllerResponse(parameter) {
   .... // self.parameter = parameter
  }
}

There are two options:

A) with Segue

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
   let goNext = segue.destinationViewController as ChildViewController
   goNext.delegate = self
}

B) without Segue

let goNext = storyboard?.instantiateViewControllerWithIdentifier("childView") as ChildViewController
goNext.delegate = self
self.navigationController?.pushViewController(goNext, animated: true)

Method Call

self.delegate?.childViewControllerResponse(parameter)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Boggarapu
Solution 3 Darshan Kunjadiya
Solution 4 Harry Bloom
Solution 5 lojals
Solution 6 RsD