Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSNotification addObserver:someOtherClass

Tags:

iphone

I need to pass a message up to a controlling class (which creates an instance of the class which will be sending the message) So, I cannot directly reference the class name in my file, without either making it a Global (which is ridiculous to do if "NSNotification" advertises to be able to pass all kinds of messages, regardless of where / what class they are.

So without further ado...

(calling from Say ClassB)

ClassA creates instance of ClassB

Now in ClassB, I need to pass messages regarding button presses back up to ClassA

(insdie ClassB)
- (void)viewDidLoad
{
  [[NSNotificationCenter defaultCenter] addObserver:ClassA 
                                        selector:@selector(doLoginAction)      
                                        name:@"SomeButton" 
                                        object:nil];
  [super viewDidLoad];
}

This will NOT compile, even when I include, sorry, "#import "ClassA.h" Now if I do something stupid like,

ClassA *classa = [[ClassA alloc]init];

and then use this Newly created instance of classa in addObserver:classa it will compile, but as I thought, will do absolutely nothing... (I knew that, but surprisingly this kind of code is prevalent in Iphone programming books...) So I tried it anyway.

But if I put this function in ClassA and use addObserver:ClassB it will get called, but will cause a stack dump unrecognized selector sent to instance or use addObserver:self.

I am tempted to delete Xcode and go back to vim and use a good old "C" callback...

like image 314
chinasailor Avatar asked Dec 28 '22 02:12

chinasailor


1 Answers

So, if I get it right, you have a ClassA which creates instances of ClassB. Those instances, in turn, should send notifications directly to ClassA without knowing anything about it.

If that is correct, then NSNotificationCenter is exactly what you need.

In ClassA implementation add an initialialize method like this:

@implementation ClassA

+ (void)initialize
{
    [[NSNotificationCenter defaultCenter]
        addObserver:self
           selector:@selector(YourSelector:)
               name:@"YourNotificationName"
             object:nil];
}

+ (void)YourSelector:(NSNotification *)notification
{
    NSDictionary *userInfo = [notification userInfo];

    // ...
}

// ...

@end

Then, instances of ClassB should post their notifications using only its name:

@implementation ClassB

- (void)postNotification
{
    NSDictionary *userInfo = ...;    // may be nil
    [[NSNotificationCenter defaultCenter]
        postNotificationName:@"YourNotificationName"
                               // the same name is used in the `addObserver` call
                               // in the previous code snippet
                      object:nil
                    userInfo:userInfo];
}

// ...

@end

To sum it all up, you do not need to know anything about the receiver of notifications if you are using NSNotificationCenter. In fact, you may subscribe as many objects as you like to receive the same notification, and each of them will call its appropriate method (specified in addObserver) upon receiving the notification object.

Please remember that in the case when you add a class instance as an observer, rather than the class object itself, you should call [[NSNotificationCenter defaultCenter] removeObserver:self] in that instance's dealloc method.

like image 84
Alexei Sholik Avatar answered Jan 12 '23 23:01

Alexei Sholik