NSNotification多个观察者,只有一个被调用

时间:2014-02-21 09:56:43

标签: ios nsnotificationcenter nsnotification

我有2名观察员注册。其中一个在appDelegate中,另一个在myViewController中。当我在myViewController中时,我只希望得到两个通知,一个来自appDelegate,它全局执行一些方法,另一个来自myViewController,它执行一些其他方法。但是,只有appDelegate中的那个被调用。如果我在appDelegate中删除观察者,则会调用myViewController中的观察者。实际上,我可以在appDelegate中使用observer方法并找出当前的视图控制器并在myViewController中执行该方法的代码。但是,我只是不想乱appDelegate。两个相同的代码,但是当调用viewWillDisappear()方法时,我在myViewController中删除了观察者。有任何想法吗?感谢。

的appDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[NSNotificationCenter defaultCenter] addObserver:self   
                                             selector:@selector(someMethod:)
                                                 name:@"someName"
                                               object:nil];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"someName"
                                                        object:nil
                                                      userInfo:someUserInfo];
}

- (void)someMethod:(NSNotification *)notification
{
    // gets called
}

myViewController

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(someMethod:)
                                                 name:@"someName"
                                               object:nil];
}

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

    [super viewWillDisappear:animated];
}

- (void)someMethod:(NSNotification *)notification
{
    // not called
}

3 个答案:

答案 0 :(得分:2)

在下面的代码中,您在观察之前发布了

 (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"someName"
                                                        object:nil
                                                      userInfo:someUserInfo];

    [[NSNotificationCenter defaultCenter] addObserver:self   
                                             selector:@selector(someMethod:)
                                                 name:@"someName"
                                               object:nil];
}

*原创* 这里有很多可能的问题:

通知名称拼写错误= @“someName” - 如果要从其他类中观察红色,请考虑创建

<。>在.h(两个类都导入) 包括

extern NSString * const XXXSomeNameForSomeNotification; 

在相应的.m

NSString * const XXXSomeNameForSomeNotification = @"someName";

这是确保他们全部观察/发布正确通知的一种方法

如果那不是你的问题,那么尝试添加观察来自viewDidLoad的通知或者在viewDidAppear之前调用的另一个方法,因为它可能是在它实际发布时没有观察到你的通知。添加断点来观察这一点。

答案 1 :(得分:0)

我认为根据您发布的代码原因是

- (void)viewWillDisappear:(BOOL)animated
{

[[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:@"someName"
                                              object:nil];

[super viewWillDisappear:animated];

}

上述方法将删除观察当前视图是否不在屏幕上的通知。

您也可以移动

[[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:@"someName"
                                              object:nil];

- (void) dealloc
{
       [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:@"someName"
                                                  object:nil];
}

这样,您只能在删除视图控制器表单内存时停止观察通知。如果你在屏幕上,你可能想要检查被调用的方法。

答案 2 :(得分:0)

看起来,您的通知是在加载视图之前发布的。请参阅添加一些日志。

或试试这个 -

    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

        [[NSNotificationCenter defaultCenter] postNotificationName:@"someName"
                                                            object:nil
                                                          userInfo:someUserInfo];
    });