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

时间:2015-06-11 07:16:14

标签: objective-c cocoa nsnotificationcenter

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

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

在B类中,我想在系统区域发生变化时向观察者发送zoneChange消息。

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

上面的代码有效。当用户在Mac上更改时区时,会调用zoneChange方法。但是,编译器给出了关于@selector的警告:未声明的选择器“zoneChange:”。令我感到困惑的是,由于zoneChange是一种私有方法,为什么B类中的@selector会超出A类?有人可以帮我解释一下吗?

2 个答案:

答案 0 :(得分:1)

私有方法只是:私有。它们仍然存在,它们只是对外界保密。 Objective-C没有内置任何内容来检查调用方法的位置并在运行时进行投诉;关于未声明的选择器的编译时警告正是B类无法看到您期望的方法!

答案 1 :(得分:1)

在Objective-C的世界中,当您编写[receiver zoneChange:note]时,您实际上是向接收对象zoneChanged:发送消息receiver),而不是直接进行函数调用。虽然最终有一些C函数被调用,但Objective-C消息仍然与传统的C函数有很大不同 - 我认为这就是为什么你感到困惑。

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