我正在使用NSNotificationCenter在两个类之间进行通信。我的问题是,虽然我点击一次按钮(并且该按钮仅触发一次)但我无意中仅通过一次调用NSNotificationCenter产生了越来越多的通知。
以下是对问题的更好解释,代码为:
我的两个课程是 mainView 课程和菜单课程。
点击 mainView 类中的视图后,它会启动由菜单类创建并管理的视图。初始化 mainView 时会调用此代码:
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];
这个手势识别器会在 mainView 类中触发此方法:
- (void) onTapped: (UIGestureRecognizer*) recognizer {
NSLog(@"tap");
[menu displayMenu];
}
这是菜单类初始化的方式:
- (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;
}
这是菜单类中的displayMenu
方法:
- (void) displayMenu {
[viewForMenu addSubview:menuView];
}
菜单类还有一个clearMenu
方法:
- (void) clearMenu {
[menuView removeFromSuperview];
}
这是UICollectionView中每个单元格的代码,包含在菜单类中:
- (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;
}
这会在我的菜单类中调用onButtonTapped:
方法:
- (void) onButtonTapped:(UIGestureRecognizer*) recognizer {
NSInteger buttonTapped=[[recognizer view] tag];
[[NSNotificationCenter defaultCenter] postNotificationName:@"ItemChange" object:nil userInfo:@{@"selected":@(buttonTapped)}];
[self clearMenu];
}
我的 mainView 类会使用以下代码获取此通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil];
这会在我的 mainView 类中调用onChangeItem:
方法:
- (void) onChangeItem: (NSNotification*) notification {
NSLog(@"change item to %d",[[[notification userInfo] objectForKey:@"clock"] intValue]);
}
这就是代码。
好的,这就是问题:第一次显示菜单我在日志中得到了这个:
...[43023:11f03] tap
...[43023:11f03] button tapped : 1
...[43023:11f03] change item to 1
这很好,这就是我的期望。但是第二次我得到了这个:
...[43023:11f03] tap
...[43023:11f03] button tapped : 1
...[43023:11f03] change item to 1
...[43023:11f03] change item to 1
我第三次得到这个:
...[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
等等。菜单项上的每次连续点击都会使通知呼叫量加倍。
首先,我认为我正在添加多个视图,从而导致多个按钮点按,因此会有多个通知调用。
但是从我的日志中可以看出,情况并非如此。 这些按钮只接收1个点击事件 - 这只会触发1个通知 - 但接收类会收到多个通知。
任何人都可以向我解释这个吗?
很抱歉这篇冗长的帖子!
答案 0 :(得分:32)
好吧,我假设[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil];
被多次添加。
我喜欢在添加观察者之前删除任何潜在的观察者,如下所示:
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"ItemChange" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChangeItem:) name:@"ItemChange" object:nil];
这样只会有一个观察者回调。
答案 1 :(得分:1)
问题:我遇到了同样的问题,观察者打了两次,有时是三次。
场景
- 用户点击注销按钮
HomeViewController
被撤消,并显示了LoginViewController
屏幕- 当用户第二次登录时
- 观察员被叫两次(有时三次)
问题是我的[[NSNotificationCenter defaultCenter] removeObserver:self];
的{{1}}方法中的dealloc
根本没有被调用,实际上是从通知中心一起删除了一个对象。
ℹ️
HomeViewController
是一个Objective-C选择器,由 当对象不再归对象所有时,Objective-C运行时 应用程序的任何部分。
解决方案:制作了自己的方法dealloc
,并在用户点击dispose
时调用它。
logout