Why @selector can call a method which is declared in an implementation file?

158 views Asked by At

I have declared (between @interface and @end) and implemented a method in the .m file of Class A. For instance:

- (void)zoneChange:(NSNotification *)note
{
    NSLog(@"The system time zone has changed!");
}

And in Class B, I want to send zoneChange message to a observer when the system zone is changed.

[[NSNotificationCenter defaultCenter] addObserver:anObserver
                                         selector:@selector(zoneChange:)
                                             name:NSSystemTimeZoneDidChangeNotification
                                           object:nil];

The code above works. When user changes the time zone on Mac, zoneChange method get called. However, the compiler gives me a warning about the @selector: Undeclared selector "zoneChange:". What confused me is that sincezoneChange is a private method, why can it been seen by the @selector in Class B beyond the Class A? Anyone can explain it for me?

2

There are 2 answers

2
andyvn22 On BEST ANSWER

Private methods are just that: private. They still exist, they're just kept secret from the outside world. There's nothing built in to Objective-C to check where a method is being called from and complain at runtime; that compile-time warning about an undeclared selector is exactly the failure of Class B to see the method that you expect!

0
Renfei Song On

In the world of Objective-C, when you write [receiver zoneChange:note], you are actually sending a message (zoneChanged:) to the receiving object receiver, rather then making a function call directly. Although eventually there are some C-functions called, the Objective-C messages are still very different from the traditional C functions - I think that's why you are confused.

C functions are "static." The process of calling a C function is in fact just jumping to some point and executing some code, which is determined at compile time. However, messages are processed at run-time. Objective-C is a dynamic language, which means you can add methods or even classes at run time. As a result, there is no way to determine whether a class implements (or responds) to one particular selector at compile-time. Case in point, some accessors of NSManagedObject are added at run time when called. So despite the warning, actually you can send any message to any object (including nil) using performSelector without getting a compilation error.