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

时间:2013-04-09 05:31:29

标签: iphone ios objective-c nsobject

我正在使用套接字编程。我只想澄清与从mobileorchard.com - Chatty下载的代码相关的疑问。在R& D的时候,我在 ChatRoomViewController.m 文件中看到了一个函数调用

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

当我在 Room.m 文件中看到,用于执行上述调用;它是

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

我用google搜索“doesNotRecognizeSelector:”,根据Apple的错误处理,说明“只要对象收到无法响应或转发的aSelector消息,运行时系统就会调用此方法。”我的问题是为什么开发人员调用 broadcastChatMessage:fromUser:函数,如果它没有在那里使用并处理哪个方法的“未找到选择器”异常?

根据Stackovrflow,它用于创建抽象类,根据此Question,它可以避免“不完整实现”警告。

我仍然没有理解为什么在Chatty Code中使用该方法,请帮助我理解使用该方法的原因。

2 个答案:

答案 0 :(得分:12)

这是每个NSObject派生对象上存在的方法,当在运行时调用中无法识别方法时,该方法会触发异常路径。例如,如果您尝试向名为NSString的{​​{1}}发送邮件,那么它就会结束,因为这不是-foo上的有效方法。

在这种情况下,Chatty类NSString是一个永远不会直接使用的基类。 RoomLocalRoom派生自它,这两个类都提供了RemoteRoom的重写实现。没有人会调用那个基类版本,但是为了“完整性”,程序员已经保证子类格式必须通过实现该方法来覆盖它,然后转而调用它来触发异常。

事实是,这不是特定的惯用Objective-C。 “抽象”类是来自C ++和其他语言的概念;它的基类只存在于子类的“模式”中。 (在ObjC中,通常通过在没有有意义的状态时创建正式的-broadcastChatMessage:fromUser来完成,因为(大多数)不在这里)。

请注意,对@protocol的调用是任意的。没有必要在这里避免编译器警告(因为该方法实际上是已实现的),并且原始编写者可能很容易直接抛出异常,或者不做任何事情。

答案 1 :(得分:4)

在我看来,你已经回答了自己的问题。没有方法可以在Objective-C中创建抽象类,所以最接近的方法是使用覆盖抛出异常所需的方法。如果在子类中重写此方法,则将不再调用doesNotRecognizeSelector:。基本上,它是一种让开发人员承诺在他们的子类中实现此方法的方法。

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