【问题标题】:Why do we call doesNotRecognizeSelector: method?为什么我们调用 doesNotRecognizeSelector: 方法?
【发布时间】:2013-03-31 09:56:27
【问题描述】:

我正在处理套接字编程。我只是想澄清一个与我从 -mobileorchard.com - Chatty 下载的代码有关的疑问。在研发期间,我在 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];
}

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

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

我仍然不明白为什么在Chatty Code 中使用该方法,请帮助我了解使用该方法的原因。

【问题讨论】:

  • 看起来应用程序的原始开发人员试图模拟 C++ 抽象基类的特性,因为它的实例是无效的。它只是让方法什么都不做或返回占位符值(通常为 0 或 NULL)的一种更极端的形式。

标签: iphone ios objective-c nsobject


【解决方案1】:

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

在这种情况下,Chatty 类Room 是一个从未直接使用的基类。 LocalRoomRemoteRoom 派生自它,并且这两个类都提供了 -broadcastChatMessage:fromUser 的覆盖实现。从来没有人调用过那个基类版本,但是为了“完整性”,程序员保证子类必须通过实现方法来覆盖它,然后转身调用它来触发异常。

问题是,这并不是特别惯用的 Objective-C。 “抽象”类是来自 C++ 和其他语言的概念;它是仅作为子类的“模式”存在的基类。 (在 ObjC 中,这通常是通过在没有有意义的状态时创建一个正式的 @protocol 来完成的,因为那里(大部分)不在这里)。

请注意,对-doesNotRecognizeSelector: 的调用是任意的。这里没有必要避免编译器警告(因为该方法实际上已实现),并且原始作者可能很容易直接抛出异常,或者什么都不做。

【讨论】:

  • 我认为苹果官方文档首先看到-doesNotRecognizeSelector: API 的文档说-“但是,它们可以在程序代码中用于防止方法被继承。”
【解决方案2】:

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

另外,正如你所提到的,如果你不把它放进去,那么编译器会发出警告,因为头文件中定义的方法不存在任何实现。这将执行与未实现相同的行为,但编译器会意识到您是故意这样做的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    相关资源
    最近更新 更多