3

So I have a basic app, here is how it works. I have a root view controller called A and a table view controller called B. And when the user selects a row in B I pop back to the root view controller A.

And what I am trying to do is to pass the data of the row that was selected as a NSString back to the root view controller A. And then use this string to "do something" depending on the string.

I have tried using the NSNotification method but then I can't use the string to do something.

Heres what I have tried:

//tableViewB.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"passData" object:[[_objects objectAtIndex:indexPath.row] objectForKey:@"title"]];
    [self.navigationController popToRootViewControllerAnimated:YES];
}
//rootViewA.m
-(void)dataReceived:(NSNotification *)noti
{
     NSLog(@"dataReceived :%@", noti.object);

}
-(void)viewDidLoad {
  [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dataReceived:) name:@"passData" object:nil];
}

What I am trying to do is some more like you can do when you push a viewController and use the perpareForSegue Method.

Thanks in advance for your help.

  • In addition to the other answers posted, you could use an unwind segue to go back rather than popToRootViewController, which would allow you to use prepareForSegue the same way you do for a forward segue. – rdelmar May 28 '14 at 03:53
  • @rdelmar how would I go about using that in the didSelectRowAtIndexPath method? –  May 28 '14 at 04:07
  • You do it just like any other segue that you're going to call manually -- you give your segue an identifier, and call performSegueWithIdentifier:sender:. You could also connect the unwind segue directly from the cell, in which case you shouldn't implement didSelectRowAtIndexPath at all. – rdelmar May 28 '14 at 04:13
  • @rdelmar so you are saying have a push segue going from the TableView B to the root A and then call performSegueWithIdentifier:sender: in the didSelectRowAtIndexPath method? –  May 28 '14 at 04:15
  • No, not a push segue, an unwind segue. If you're connecting it from the controller (B), then you would call performSegueWithIdentifier:sender: in the didSelectRowAtIndexPath method, but if you connect the segue directly from the cell, then you don't need to call anything. – rdelmar May 28 '14 at 04:17
  • @rdelmar when I do the control click and drag I don't see unwind segue as an option? –  May 28 '14 at 04:19
  • That's not how you create an unwind segue. Have a look at the answer here, http://stackoverflow.com/questions/12561735/what-are-unwind-segues-for-and-how-do-you-use-them – rdelmar May 28 '14 at 04:21

3 Answers3

1

You're doing the right thing but with the wrong parameters. The object: param in the notification post is the sending object. There's another post method that allows the caller to attach userInfo: as follows:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    // notice the prettier, modern notation
    NSString *string = _objects[indexPath.row][@"title"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"passData"
                                                        object:self
                                                      userInfo:@{"theString" : string }]
    [self.navigationController popToRootViewControllerAnimated:YES];
}

On the receiving end, just get the data out of the notification's user info with the same key:

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

     NSLog(@"dataReceived :%@", notification.userInfo[@"theString"]);
}
danh
  • 55,236
  • 10
  • 89
  • 124
  • okay yes that works but I need to be able to use the string that I pass back to A in the viewWillAppear method, which I can do with this. Correct? –  May 28 '14 at 03:51
  • Yes. If the string is needed to update the view, you can do that right there in the dataReceived method. Or if you want to save it to a view controller property in dataReceived, you can use it anytime thereafter, including just before that view controller's view reappears. – danh May 28 '14 at 03:53
1

Use delegate: it would be better than NSNotification

tableView.h:

@protocol tableViewDelegate
-(void) tableViewSelectRowWithString:(NSString*)str;
@end

@interface tableView:UITableViewController //or something like this

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

tableView.m:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath     {
[self.delegate tableViewSelectRowWithString:@"your string"];
[self.navigationController popToRootViewControllerAnimated:YES];
}

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

//rootViewA.h

@interface rootViewA : UIViewController<tableViewDelegate>

//rootViewA.m

//When create tableView and push view:
tableView *t = ....;
tableView.delegate = self

-(void) tableViewSelectRowWithString:(NSString*)str{//use string}
nmh
  • 2,477
  • 1
  • 13
  • 27
  • When I add the code into my tableView.h I get a bunch of errors on the code. I just pasted it below the @intface line. Is there a specific place it needs to go? –  May 28 '14 at 04:06
0

Try this may be help full

    MyAController *myController = (MyAController *)[self.navigationController.viewControllers objectAtIndex:0];
    myController.myText = @"My String" ;
    [self.navigationController popToViewController:myController animated:YES];

I have use many time this .. It's working fine .. Note : replace your class name and string in this . Thanks :)

Jogendra.Com
  • 5,980
  • 2
  • 24
  • 33
  • This might work for the OP, but please take note that the viewControllers array is a stack. In general, to get the vc below the top, use navVC.viewControllers[MAX(0,navVC.viewControllers.length-2)]. The one at length-1 is the top, the one at zero is the root. – danh May 28 '14 at 23:33