关于iphone:为什么我们调用doesNotRecognizeSelector:方法?

Why do we call doesNotRecognizeSelector: method?

我正在编写socket编程,我只是想澄清一个与我从-mobileorchard.com-chatty下载的代码有关的疑问。在R&D期间,我在chatroomviewcontroller.m文件中看到一个函数调用

1
 [chatRoom broadcastChatMessage:input.text fromUser:[AppConfig getInstance].name];

当我看到在room.m文件中执行上述调用时,它是

1
2
3
4
5
- (void)broadcastChatMessage:(NSString*)message fromUser:(NSString*)name
{
    // Crude way to emulate an"abstract" class
    [self doesNotRecognizeSelector:_cmd];
}

我在google上搜索了"doesnoTrecognizeSelector":根据Apple ITS的错误处理,声明"运行时系统在对象接收到它无法响应或转发的选择器消息时调用此方法。"我的问题是,开发人员为什么调用BroadcastChatmessage:FromUser:Function(如果它在那里不使用),并处理whicH方法的"未找到选择器"异常?

根据stackovrflow,它用来创建抽象类,根据这个问题,它避免了"不完全实现"的警告。

我仍然不明白为什么这个方法会被用在那些闲聊的代码中,请帮助我理解为什么使用这个方法。


这是存在于每个NSObject派生对象上的方法,当在运行时调用中无法识别某个方法时,该方法会触发异常的路径。例如,如果您试图向一个名为-fooNSString发送一条消息,它将在那里结束,因为这不是NSString上的有效方法。

在这种情况下,聊天类Room是一个从未直接使用过的基类。LocalRoomRemoteRoom从中派生,这两个类都提供了-broadcastChatMessage:fromUser的最重要的实现。没有人调用过这个基类版本,但是为了"完整性",程序员已经保证子类必须通过实现该方法来覆盖它,然后反过来调用它来触发异常。

事实上,这不是一个具体的惯用对象-C。一个"抽象"类是C++和其他语言的概念;它的基类只存在于一个"模式"中。(在objc中,这通常是通过在没有意义的状态下创建一个正式的@protocol,因为这里(大部分)没有意义的状态)。

注意,对-doesNotRecognizeSelector:的调用是任意的。这里不需要避免编译器警告(因为实际上实现了该方法),而且原始编写器可以很容易地直接抛出异常,或者什么也不做。


在我看来你已经回答了你自己的问题。在Objective-C中没有生成抽象类的方法,因此最接近的方法是使用需要重写抛出异常的方法。如果在子类中重写此方法,那么将不再调用doesNotRecognizeSelector:。基本上,这是让开发人员承诺在其子类中实现此方法的一种方法。

另外,正如您提到的,如果不将其放入,编译器将发出警告,因为在头中定义的方法不存在任何实现。这将执行与不实现它相同的行为,但编译器将认识到您是故意这样做的。