Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 387
Sosily Avatar asked Nov 22 '12 09:11

Sosily


4 Answers

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];
like image 175
Atif Alvi Avatar answered Oct 14 '22 22:10

Atif Alvi


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]; 
...
like image 45
Saliom Avatar answered Oct 14 '22 22:10

Saliom


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
like image 35
Harry Bloom Avatar answered Oct 14 '22 22:10

Harry Bloom


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?

like image 1
John Avatar answered Oct 14 '22 22:10

John