0

I am troubling with an issue and I cannot be able to solve it!

The scenario is the next one: - I have 4 view controller (main view controller is an UITableView, settingsVC, messsageDetailController and moreInfoVC). - I also have a listener (NSObject) which is listening a port for different events to receive.

Then, functionality is the next one: - I launch the listener to receive those events. When the listener receives a new event, this listener communicates to the mainViewController, and from this mainVC I create a new instance of messageDetailController. *Im using the below code (mainVC):

[self performSegueWithIdentifier:@"MessageDetail" sender:self];

I got all this functionality, but my problem starts when my listener receives more than one event and then, consequently, I create more than one messageDetailController reference. That problem affects directly to my NavigationController which is popping me out next messages: - nested push animation can result in corrupted navigation bar - Unbalanced calls to begin/end appearance transitions for . - Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

I hope that I explained myself properly and anyone could help me.

rubrin
  • 99
  • 2
  • 10
  • It's hard to advise you without knowing more about what behavior you want. What do you want to happen when the listener receives a second event? Do you want the messageDetailController to show something about that new event only? Do you want to show info about both events, and keep adding as new events come in? – rdelmar Apr 17 '13 at 16:00
  • I only want to show the new information that I have received in my listener. Thats why I create a new messageDetailController... I dont know if its the best idea to be honest... – rubrin Apr 17 '13 at 16:05

2 Answers2

0

You probably don't want to use a segue to do what you're trying to do here, because a segue always creates a new view controller. It would be better to push to the messageDetailController in code, so that you can put an if clause in there that only creates and pushes the controller if one doesn't exist. When a second event comes in, you want only to change the value of what you're displaying. The code could be something like this (in main view controller, I guess, if that's what gets the info from the listener).

if (! messageDetailController) {
    MessageDetailController *messageDetailController = self.storyboard instantiateViewControllerWithIdentifier:@"MessageController"];
    messageDetailController.detailItem = infoFromListener;
    [self.navigationController pushViewController:messageDetailController animated:YES];
}else{
    messageDetailController.detailItem = infoFromListener;
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • Im still having the same behaviour. For example, if you are in another view controller (settingsVC), and in that case, the listener receives a new message, im gonna show this message on messageDetailController. But, at the moment I pressed on the back button (messageDetailController) to go to mainVC (because is the rootVC), my navigationController shows me the previous barNavigationController (settingsCV).... – rubrin Apr 17 '13 at 16:34
  • @rubrin, well if your order is mainVC --> settingsVC --> messageDetailVC then that's the behavior you're going to get. If you don't want that, then you need to make a different design. It's not at all clear what you want to happen when a new message comes in -- do you want it to not only update messageDetailVC, but also to show that vc no matter what view you are looking at? Do you just want it to update, but the user won't see it until they navigate back to it? You need to fill in more details about what you want. Usually, a settings controller would not be in the path between other vc's. – rdelmar Apr 17 '13 at 20:12
  • User can be in any of the different VC. Order is mainVC-messageDetailVC-moreInfoVC and mainVC-settingsVC. So, independently which VC was, when the listener receives a new message I want to show it. I hope it is clearly enough now. thanks rdelmar – rubrin Apr 18 '13 at 08:31
  • @rubrin, You need to have some logic in mainVC, that looks at self.navigationController.viewControllers when a new message comes in from the listener. If the count of that is 1, then you need to push to messageDetailVC. If it's 2, that means you're in messageDetailVC, and you just need to update what it's showing. If it's higher than 2, then you should popToViewController:messageDetailController which will take you directly back to that controller if you're in either of the last two controllers. – rdelmar Apr 18 '13 at 15:41
  • I got the final solution @rdelmar! Finally what I have done its to remove all the VC saved in the navigationController stack except my mainVC. Solution its something like that: `NSMutableArray *array = [NSMutableArray arrayWithArray: self.navigationController.viewControllers]; for(NSInteger i = ([array count] - 1); i > 0; i--) if(i != 0) [array removeObjectAtIndex:i]; self.navigationController.viewControllers = array; [self performSegueWithIdentifier:@"MessageDetail" sender:[settingsReference actualView]];` – rubrin Apr 18 '13 at 16:51
0

Solution:

NSMutableArray *array = [NSMutableArray arrayWithArray::self.navigationController.viewControllers];

for(NSInteger i = ([array count] - 1); i > 0; i--)
    if(i != 0)
        [array removeObjectAtIndex:i];

self.navigationController.viewControllers = array;

[self performSegueWithIdentifier:@"MessageDetail" sender:[settingsReference actualView]];
rubrin
  • 99
  • 2
  • 10