在Xcode中抑制类方法未找到的警告

6

我有一个类,其方法在运行时确定,正如我在这里所述。这很好用,但现在我的代码中充斥着以下警告:

Class method '+objectIsNotNil:' not found (return type defaults to 'id')

虽然这些警告实际上不会影响构建流程,但它们会让人感到非常烦人,并且使人难以发现相关的警告信息。是否有一种方法可以仅针对Assert类禁用它们(可能是某种宏定义)?如果这不可行,则是否有办法关闭整个构建过程中的警告?
3个回答

9

一个替代方法是使用performSelector:withObject:来代替直接调用方法。所以,不要再这样写:

[Assert objectIsNotNil:object];

您可以选择:

[Assert performSelector:@selector(objectIsNotNil:) withObject:object];

它看起来不够漂亮,但它将消除警告。此外,这个模式适用于您想要的任何选择器。为了使事情看起来更好一些,您可以按照以下方式使用宏:

#define ASSERT_PRECONDITION(sel, obj)  [Assert performSelector:@selector(sel) withObject:obj]

这样,你的断言将会是这个样子:
ASSERT_PRECONDITION(objectIsNotNil:, object);

我真的很喜欢这个解决方案。它不需要我使用任何编译器标志,因为它不使用任何警告。此外,宏可以消除一些丑陋的代码,这非常有帮助。我唯一的问题是,使用performSelector:只能让你使用最多两个参数,并且这些参数必须是对象。我可能会使用`objc_msgSend',因为它消除了这些限制。感谢您的帮助。 - LandonSchropp

2

这些情况应该极为罕见...

我声明了一个隐藏协议,其中声明了具有适当签名的方法。所谓“隐藏”,是指它只被需要它们的翻译所包含。

@protocol MONRuntimeClassInterface
+ (BOOL)objectIsNotNil:(id)object;
@end

这似乎可以解决问题,但实际上它破坏了我原来解决代码重复的方法。 我真正需要的是一种抑制警告的方法。 - LandonSchropp
1
@helixed,由于Objective-C是C家族语言,你应该纠正这些警告。当编译器不知道类/实例方法的签名时,它会假定每个参数和返回类型都是“id”。编译器在传递和返回参数时会为您执行许多好事情-提升、转换、调整对齐等等。同样的问题也困扰着C程序员的隐式声明。(cont) - justin
1
你应该考虑到这个公式的偏差(例如传递或返回非对象)可能会导致未定义的行为。为了禁用此检查,您可以使用GCC_WARN_UNDECLARED_SELECTOR = YES,但我强烈不建议禁用它。有更好的方法来解决这个问题。祝你好运。 - justin
1
+1,这是正确的答案。如果您直接调用一个方法,它必须被声明。 - Anomie
2
@helixed:你可以相信任何想法,但如果你返回的不是"id",那么你可能会遇到麻烦。 - Anomie
显示剩余4条评论

1

简单的答案:

你不想这样做。如果我理解你的问题正确,你也不需要这样做。你在链接中描述的 Predicate 类中定义了所有相关的方法,而 Assertion 只是将它们转发。包括 Predicate.h 并确保一切都在接口中声明应该可以正常工作。就像在类型为 id 的对象上调用的方法一样,只要编译器知道至少有一个类在该编译单元中实现了相同名称的类方法,它就会认为在 Class 对象上调用的方法已找到。

另一种答案:

如果你真的想要抑制编译器警告,例如在编译时调用一个不存在的方法,则需要使用NSObject的performSelector:方法或运行时函数objc_msgSend()。这不会在编译时检查匹配的方法。然而,对于一些C类型,你可能想要作为参数传递(如浮点数和某些较大的结构体),编译器需要知道它们的类型。在没有方法定义的情况下,它需要你提供信息。performSelector:通过仅接受id类型的对象来工作。objc_msgSend在调用之前需要将其强制转换为具有适当签名的函数(在某些情况下,替换为变体函数)。Mike Ash在这里很好地解释了这个过程here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接