从UITabBarController多次调用NSNotification

时间:2014-01-09 19:33:56

标签: ios objective-c uitabbarcontroller nsnotificationcenter

我有UITabBarController,有4个标签。这些标签中的每一个都是单独的UIViewController。我在这4个VC中的每一个上都有对象,这些对象在按某个对象时使用NSNotification来执行操作。 4个VC都以相同的方式响应通知,因为它是每个页面上的类似对象。按下此对象时,它会在当前视图控制器上显示一个视图。问题是,如果我移动到其他3个选项卡中的任何一个,那么该视图也在他们的VC上。这是因为当在任何VC上按下通知时,所有4个选项卡上的响应都被响应。我需要它只响应用户当前所在的VC而不是标签栏中的任何其他VC。

有没有办法让它正常工作?也许是一个阈值,您可以在其中设置通知在被调用后执行其选择器的次数?这样我可以将它设置为1,并且在任何给定时间如果调用该通知,则只能调用一次选择器。

我正在使用的对象实现类型要求我使用NSNotificatio n,因此无法改变我的交互方式。

编辑:

viewDidLoad方法位于我标签栏中4个VC的顶级VC上。它们中的所有4个都直接使用它或继承它。

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

动作处理程序:

- (void) didSelectItemFromCollectionView:(NSNotification *)notification
{
    NSDictionary *cellData = [notification object];

    if (cellData)
    {
        NewVC *pushToVC = [self.storyboard instantiateViewControllerWithIdentifier:@"PushToVC"];

        [self.navigationController pushViewController:pushToVC animated:YES];
    }
}

4个VC中的每一个都是UITableViewController,并且具有可以按下的对象的单元格。此NSNotificationCenter操作允许操作工作。

2 个答案:

答案 0 :(得分:4)

您必须在每个NSNotificationCenter

-addObserver:selector:name:object:中实施-viewDidLoad的{​​{1}}方法

实施例

viewController

不要在- (void)viewDidLoad { //... [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) name:@"TestNotification" object:nil]; } 中将其移到-viewDidLoad内,而是在-viewWillAppear中实施removeObserver:name:object:

这样,只有当前 on -viewWillDisappear才会响应通知。

实施例

viewController

- (void)viewWillAppear:(BOOL)animated
{
    //...
    [NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(doSomething:) 
                                                name:@"TestNotification"
                                              object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    //...
    [NSNotificationCenter defaultCenter] removeObserver:self
                                                   name:@"TestNotification"
                                                 object:nil];
}

修改

你(@Jonathan)评论道:

  

我非常感谢你的回答,这对我帮助很大!一世   实际上遇到了这个问题发生的另一个场景,我是   不知道如何弄清楚。现在我有一个VC呈现   另一个VC模态。每个人都有相同的观察员   NSNotification。当我进入时,一切都表现得非常好   模态提出VC,但是一旦我解雇那个VC并返回   潜在的,我有相同的问题通知   多次召唤。你对这方面的解决方案有所了解吗?   情况?

现在......关于这个......

首先......注意:

  1. 多个- (void)doSomething:(NSNotification *)userInfo { //... //if you push a viewController then the following is all you need [self.navigationController pushViewController:vcSomething animated:YES]; //however.... if you're instead presenting a viewController modally then //you should implement "-removeObserver:name:object: in this method as well //[NSNotificationCenter defaultCenter] removeObserver:self // name:@"TestNotification" // object:nil]; //[self presentViewController:vcSomething // animated:YES // completion:nil]; //OR... in the completion parameter as: //[self presentViewController:vcSomething // animated:YES // completion:^{ // [NSNotificationCenter defaultCenter] removeObserver:self // name:@"TestNotification" // object:nil]; // }]; } 将多次注册指定的通知(表示...相同的通知被注册N次将调用目标选择器N次
  2. -addObserver:selector:name:object:提示ViewController(称之为儿童)将 NOT 调用{{1}父母的 在哪里......
  3. 解雇儿童 viewController仍然会调用
  4. -viewWillDisappear:

    这会在逻辑中产生不平衡,如果不处理(根据上面viewController方法的代码示例中的注释行),则会导致 Parent 注册多次通知(因为它-viewWillAppear:方法被调用的频率高于doSomething

    另见:similar question

答案 1 :(得分:0)

它应该只调用一次,以便永远不会被再次调用

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(methodName:) name:@"name" object:nil];
});