为什么@selector 可以调用在实现文件中声明的方法?

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

我在ClassA的.m文件中(@interface和@end之间)声明并实现了一个方法,例如:

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

而在Class B中,我想在系统区域更改时向观察者发送zoneChange消息。

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

上面的代码有效。当用户更改 Mac 上的时区时,将调用 zoneChange 方法。但是,编译器给我一个关于@selector 的警告:Undeclared selector "zoneChange:"。令我困惑的是,既然zoneChange是一个私有方法,为什么在Class A之外的Class B中的@selector可以看到它?谁能给我解释一下?

私有方法就是:私有。它们仍然存在,只是对外界保密。 Objective-C 没有内置任何东西来检查从哪里调用方法并在运行时抱怨;关于未声明的选择器的编译时警告正是 Class B 未能看到您期望的方法!

在Objective-C的世界里,当你写[receiver zoneChange:note]时,你实际上是在发送消息zoneChanged:)给接收者object receiver,而不是直接进行函数调用。尽管最终调用了一些 C 函数,但 Objective-C 消息仍然与传统的 C 函数有很大不同 - 我认为这就是您感到困惑的原因。

C函数是"static." 调用C函数的过程其实就是跳转到某个点执行一些代码,这是编译时决定的。但是, 条消息 在 运行 时处理。 Objective-C 是一种动态语言,这意味着您可以在 运行 时间添加方法甚至 classes。因此,无法在编译时确定 class 是否实现(或 响应 )到一个特定的选择器。例如,NSManagedObject 的一些访问器在调用时在 运行 时添加。因此,尽管有警告,实际上您可以使用 performSelector 向任何对象(包括 nil)发送任何消息而不会出现编译错误。