NSNotification is sent once, but received several times

I am connecting between two classes with NSNotificationCenter. My problem is that although I press a button once (and this button only works once), I inadvertently increase the number of notifications from only one call to NSNotificationCenter.

Here is the best explanation for the code problem:


My two classes are the mainView class and the Menu class.

When viewing a view in the mainView class , it starts the view created and managed by the Menu class. This code is called when mainView is initialized:

menu=[[MyMenu alloc] init]; UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapped:)]; [tap setNumberOfTapsRequired:1]; [container addGestureRecognizer:tap]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil]; 

This gesture recognizer disables this method, also in the mainView class:

 - (void) onTapped: (UIGestureRecognizer*) recognizer { NSLog(@"tap"); [menu displayMenu]; } 

This is how the Menu class is initialized:

 - (MyMenu*) init { self=[super init]; UICollectionViewFlowLayout * layout=[[UICollectionViewFlowLayout alloc] init]; menuView=[[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 200, 200) collectionViewLayout:layout]; [menuView setDataSource:self]; [menuView setDelegate:self]; [menuView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"]; [menuView setAutoresizesSubviews:YES]; [menuView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth]; [menuView setBackgroundColor:[UIColor clearColor]]; [menuView setIndicatorStyle:UIScrollViewIndicatorStyleWhite]; return self; } 

And this is the displayMenu method inside the Menu class:

 - (void) displayMenu { [viewForMenu addSubview:menuView]; } 

The Menu class also has a clearMenu method:

 - (void) clearMenu { [menuView removeFromSuperview]; } 

This is the code for each cell in the UICollectionView contained in the Menu class:

 - (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell * cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath]; [cell setTag:indexPath.row]; UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onButtonTapped:)]; [tap setNumberOfTapsRequired:1]; [cell addGestureRecognizer:tap]; NSLog(@"button tapped : %d",indexPath.row); return cell; } 

This calls the onButtonTapped: method, also in my Menu class:

 - (void) onButtonTapped:(UIGestureRecognizer*) recognizer { NSInteger buttonTapped=[[recognizer view] tag]; [[NSNotificationCenter defaultCenter] postNotificationName:@"ItemChange" object:nil userInfo:@{@"selected":@(buttonTapped)}]; [self clearMenu]; } 

This notification is picked up by my mainView class with this code:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil]; 

This calls the onChangeItem: method inside the mainView class:

 - (void) onChangeItem: (NSNotification*) notification { NSLog(@"change item to %d",[[[notification userInfo] objectForKey:@"clock"] intValue]); } 

So the code.


OK, here is the problem: the first time I display the menu, I get this in my log:

 ...[43023:11f03] tap ...[43023:11f03] button tapped : 1 ...[43023:11f03] change item to 1 

And that’s beautiful, that’s what I expect. However, the second time I get the following:

 ...[43023:11f03] tap ...[43023:11f03] button tapped : 1 ...[43023:11f03] change item to 1 ...[43023:11f03] change item to 1 

The third time I get the following:

 ...[43023:11f03] tap ...[43023:11f03] button tapped : 1 ...[43023:11f03] change item to 1 ...[43023:11f03] change item to 1 ...[43023:11f03] change item to 1 ...[43023:11f03] change item to 1 

And so on. Each subsequent click on a menu item doubles the number of notifications.


To begin with, I thought that I was adding several views and, therefore, getting a few short presses of buttons and, therefore, several notification calls.

However, as you can see from my magazines, this is not so. Buttons receive only one event-event - this turns off only one notification, but the receiving class receives several notifications.

Can someone explain this to me?

Sorry for the long post!

+8
objective-c cocoa-touch nsnotificationcenter
source share
1 answer

Well, I assume that [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil]; are added several times.

I like to remove any potential observer before adding an observer, for example:

 [[NSNotificationCenter defaultCenter] removeObserver:self name:@"ItemChange" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil]; 

That way, there will ever be only one observer callback.

+28
source share

All Articles