我正在使用套接字编程。我只想澄清与从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中使用该方法,请帮助我理解使用该方法的原因。
答案 0 :(得分:12)
这是每个NSObject
派生对象上存在的方法,当在运行时调用中无法识别方法时,该方法会触发异常路径。例如,如果您尝试向名为NSString
的{{1}}发送邮件,那么它就会结束,因为这不是-foo
上的有效方法。
在这种情况下,Chatty类NSString
是一个永远不会直接使用的基类。 Room
和LocalRoom
派生自它,这两个类都提供了RemoteRoom
的重写实现。没有人会调用那个基类版本,但是为了“完整性”,程序员已经保证子类格式必须通过实现该方法来覆盖它,然后转而调用它来触发异常。
事实是,这不是特定的惯用Objective-C。 “抽象”类是来自C ++和其他语言的概念;它的基类只存在于子类的“模式”中。 (在ObjC中,通常通过在没有有意义的状态时创建正式的-broadcastChatMessage:fromUser
来完成,因为(大多数)不在这里)。
请注意,对@protocol
的调用是任意的。没有必要在这里避免编译器警告(因为该方法实际上是已实现的),并且原始编写者可能很容易直接抛出异常,或者不做任何事情。
答案 1 :(得分:4)
在我看来,你已经回答了自己的问题。没有方法可以在Objective-C中创建抽象类,所以最接近的方法是使用覆盖抛出异常所需的方法。如果在子类中重写此方法,则将不再调用doesNotRecognizeSelector:
。基本上,它是一种让开发人员承诺在他们的子类中实现此方法的方法。
另外,正如您所提到的,如果您不将其放入,则编译器将发出警告,因为标头中定义的方法不存在实现。这将执行与不实现它相同的行为,但编译器将意识到您是故意这样做的。