0

This is a strange accumulation bug that's somehow pushing my VCs onto the Nav VC multiple times.

I have a UINavigationController with rootViewController set to CWLandingVC (lvc).

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    CWLandingVC *lvc = [[CWLandingVC alloc] init];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:lvc];
...
}

On the lvc, the user logs in and when my APIClient class gets a successful server response it posts a notification:

     NSNotification* notification = [NSNotification notificationWithName:@"sessionArrived" object:self];
     NSLog(@"APIClient Posting notification for sessionArrived");
     [[NSNotificationCenter defaultCenter] postNotification:notification];

The lvc listens for this and sends this selector accordingly:

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
           selector:@selector(toPagebookWorkspace)
               name:@"sessionArrived"
             object:client];
...
- (void)toPagebookWorkspace {
NSLog(@"lvc Calling toPagebookWorkspace for session %@.  Opening PagebookWorkspace view.", [self sessionId]);
CWWorkspaceVCViewController *wvc = [[CWWorkspaceVCViewController alloc] init];
[[self navigationController] pushViewController:wvc animated:YES];
}

The bug arises when the user logs in, successfully does pushViewController:wvc, logs back out to lvc, and logs right back in. When they do this, the notification is posted once more – which I verify with NSLog(@"Posting notification for sessionArrived"); – but the selector toPagebookWorkspace is called twice. If I repeat the bug, the selector is called 3 times, and so on. So each time I repro the bug, more and more wvc's get pushed on top of each other in the UINavigationController.

Perhaps these logs can help illuminate the strange accumulating sequence I'm seeing. For each APIClient notification post, I get an increasing number of pushViewController:wvc, rather than just 1 push.

     Logging in...
     APIClient Posting notifcation for sessionArrived
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     Pressed back on nav bar, calling viewWillDisappear


     Logging in...
     APIClient Posting notifcation for sessionArrived
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     nested push animation can result in corrupted navigation bar
     Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
     Unbalanced calls to begin/end appearance transitions for <CWWorkspaceVCViewController: 0x8067410>.
     Pressed back on nav bar, calling viewWillDisappear
     Pressed back on nav bar, calling viewWillDisappear


     Logging in...
     APIClient Posting notifcation for sessionArrived
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     nested push animation can result in corrupted navigation bar
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     nested push animation can result in corrupted navigation bar
     Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
     Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
     Unbalanced calls to begin/end appearance transitions for <CWWorkspaceVCViewController: 0x8068330>.
     Pressed back on nav bar, calling viewWillDisappear
     Pressed back on nav bar, calling viewWillDisappear
     Pressed back on nav bar, calling viewWillDisappear


     Logging in...
     APIClient Posting notifcation for sessionArrived
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     nested push animation can result in corrupted navigation bar
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     nested push animation can result in corrupted navigation bar
     lvc Calling toPagebookWorkspace for session lvcke2.  Opening PagebookWorkspace view.
     nested push animation can result in corrupted navigation bar
     Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
     Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
     Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
     Unbalanced calls to begin/end appearance transitions for <CWWorkspaceVCViewController: 0x7257930>.
     Pressed back on nav bar, calling viewWillDisappear
     Pressed back on nav bar, calling viewWillDisappear
     Pressed back on nav bar, calling viewWillDisappear
     Pressed back on nav bar, calling viewWillDisappear

If you have any idea what's up, thanks so much for your help in advance.

roro
  • 265
  • 3
  • 11
  • Try logging out when you add the observer, and make sure it isn't being added multiple times. – danielbeard Oct 08 '13 at 23:42
  • Ok, but why would I log out there? That's just at the point where the user has successfully logged in. The whole purpose of the observer there is to catch when the server has responded with verified login credentials. – roro Oct 08 '13 at 23:53
  • I do have another observer just below it, but it's listening for something else: [center addObserver:self selector:@selector(noWifiUserNotification) name:@"failedRequestGeneral" object:client]; – roro Oct 08 '13 at 23:54

1 Answers1

0

This is the expected behaviour of NSNotificationCenter: any object can add multiple observers, even for the same name, object, and selector. If you don't want to have your selector called multiple times (and it doesn't seem like you do), do the inverse of addObserver: by calling:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"sessionArrived" object:client];

(Important note: do NOT call [[NSNotificationCenter defaultCenter] removeObserver:self], as it will result in your object losing observation for all notifications its superclass(es) may have registered for. See this link for more information on why this is a bug.)

cbowns
  • 6,295
  • 5
  • 47
  • 64
  • Thanks, that did it! I added your suggested code to toPagebookWorkspace and now it doesn't get called more than once per notification. However, I still don't understand why it was getting called multiple times before. Any other thoughts there? – roro Oct 09 '13 at 00:18
  • If you were adding a notification center observer each time a user logs in, but not removing that observer when the user logs out, then logging out and in multiple times in a single app launch will accumulate observers. – cbowns Oct 09 '13 at 20:01