【问题标题】:Xcode - implementing a method, also be implemented by its primary classXcode - 实现一个方法,也由它的主类实现
【发布时间】:2013-01-18 23:48:36
【问题描述】:

我使用的是 Xcode 4.5。 在我最新的 Xcode 项目中,当我构建/编译我的程序时会弹出这个警告:

Category is implementing a method which will also be implemented by its primary class

这是导致错误的代码:

 @implementation NSApplication (SDLApplication)
 - (void)terminate:(id)sender {
    SDL_Event event;
    event.type = SDL_QUIT;
    SDL_PushEvent(&event); }
 @end

我已经做到了,所以编译器会忽略(或跳过)使用pragma code 生成的警告。

所以我的代码现在看起来像这样:

 @implementation NSApplication (SDLApplication)

 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
 - (void)terminate:(id)sender{
   SDL_Event event;
   event.type = SDL_QUIT;
   SDL_PushEvent(&event);}
 #pragma clang diagnostic pop
 @end

显然它完成了这项工作,并且一旦构建/编译,就不会生成任何警告。

我的问题是,这是一种以这种方式抑制或忽略警告的安全/正常方式吗?

我在一些帖子上读到使用子类是有利的,但是有很多人赞成和反对以这种方式使用它们......我很感激你的想法:)

【问题讨论】:

  • 如果你用all_load链接二进制文件,那么是的,它是安全的。但是,只要有可能,您应该更喜欢其他方法,因为这种方法非常神秘,虽然它有效,但对于大型项目而言,它的可维护性不是很好。

标签: objective-c pragma


【解决方案1】:

“我在一些线程上读到使用子类是有利的......”

使用子类可能是有利的,但这不是你在这里做的。

您所做的是在NSApplication 上实现(SDLApplication) Objective-C Category。在该类别中,您将覆盖NSApplicationterminate: 方法。一般来说,您应该只使用类别来向现有类添加其他方法,而不是覆盖现有方法,因为这可能会产生不可预知的结果。

你真正应该做的是子类NSApplication,这样你就可以正确地覆盖terminate:

@interface SDLApplication : NSApplication {

}

@end


@implementation

- (void)terminate:(id)sender {
   SDL_Event event;
   event.type = SDL_QUIT;
   SDL_PushEvent(&event);
   [super terminate:sender]; // this line is the key to assuring proper behavior
}

@end

覆盖的terminate: 方法的最后一步应该是调用super,以便终止方法正常工作。 (不允许在类别中使用关键字super;只能使用单词self,这就是需要子类化的原因。

确保您还将Info.plist 文件中NSPrincipalClass 键的值更改为SDLApplication 而不是NSApplication

【讨论】:

  • 是的,我知道我的原始代码没有使用子类。我只是在某处读到它是仅使用pragmas 抑制警告的替代选择。话虽如此,我并不是 100% 确定如何在 C++ 中实现子类,这确实很有帮助:) 感谢您抽出宝贵时间来解释这一点。
【解决方案2】:

没有。

覆盖(或重新实现)方法,尤其是类别中的-terminate: 等关键系统方法会导致未定义的行为。显然,退出应用程序不应该是机会游戏。子类 NSApplication 并覆盖 -terminate:(最后调用 super),然后在 info.plist 中将其指定为主体类。 Pragmas 不是警告修复者,他们只是抑制者。

【讨论】:

  • 只要方法与all_load 链接,当一个方法用协议覆盖现有方法时,它实际上已经很好地定义了会发生什么。这样做有很多正当理由,主要是修改第三方框架和非开源框架来修复错误。
  • @RichardJ.RossIII:你说的叫“猴子打补丁”,也叫“打鸭子”:)见en.wikipedia.org/wiki/Monkey_patch
  • 但我会假设基于上述实现(对 SDL 的调用),意味着他不在其中一种情况。它所需要的只是一个子类和一个额外的超级调用,而不是用他的方式来解决晦涩难懂和未来的错误。
  • 我同意。 pragma 代码只是为了抑制当时的警告。我计划通过这篇文章的答案找到关于正确处理它的建议。谢谢你的解释。
猜你喜欢
  • 2014-08-15
  • 1970-01-01
  • 2012-03-14
  • 2014-05-16
  • 2012-04-29
  • 1970-01-01
  • 2019-01-14
  • 2021-11-19
  • 1970-01-01
相关资源
最近更新 更多