【问题标题】:Using #pragma to suppress “Instance method not found” warnings in Xcode使用#pragma 抑制 Xcode 中的“Instance method not found”警告
【发布时间】:2012-02-16 11:04:03
【问题描述】:

我想使用#pragma(在 Xcode 中)来抑制警告:

警告:找不到实例方法“-someMethod”(返回类型默认为“id”)

我试过了:

#pragma GCC diagnostic ignored "-Wmissing-declarations"

还有其他几个,但没有任何效果。

什么警告导致“未找到实例方法”?

编辑

这里要求的是实际代码:

...

if (sampleRate > 0 && ![self isFinishing])  //<--- Warning here
{
    return self.progress;
}

...

以及构建日志输出:

/Users/User1/Documents/Project/branch/client/Folder/CodeFile.m:26:32:{26:32-26:50}: warning: instance method '-isFinishing' not    found (return type defaults to 'id') [3]
     if (sampleRate > 0 && ![self isFinishing])
                            ^~~~~~~~~~~~~~~~~~

【问题讨论】:

  • stackoverflow.com/questions/7264400/…的可能重复项??
  • 我已更改标题以更好地反映问题。这不是重复的,因为我确切地知道显示警告的原因。我特别想知道如何使用#pragma来抑制“未找到实例方法”警告。
  • 显示生成此警告的代码 - 可以通过稍微更改代码来抑制它。
  • @trojanfoe 按要求添加
  • 我的代码是一个错误修复,它已被添加为一个类别,以免引起问题。在项目中,我们打开了“将警告视为错误”。我无法将此代码添加到将删除错误并且无法生成警告的文件中。因此我需要一种方法来抑制这个文件。以与#pragma used(var_name) 类似的方式删除未使用的变量警告。

标签: xcode gcc warnings llvm pragma


【解决方案1】:

请参阅:https://stackoverflow.com/a/34043306/89035 以获取 #pragma 以抑制“未找到实例方法”警告。

虽然似乎不存在真正的#pragma 解决方案,但可以通过使用-w 开关来关闭单个文件中的警告。

注意:此解决方案适用于 Xcode 4.2 及更高版本

  1. 选择目标
  2. 单击“构建阶段”选项卡
  3. 在“编译源”下,将-w 开关添加到您希望禁止显示警告的文件中

【讨论】:

  • 这绝对有效。我只希望有一种方法可以使用#pragma 来抑制警告,而不是忽略可能非常大的文件上的所有警告。如果有人想出一种更准确地忽略此警告的方法,我会很高兴知道。
  • 这不是一个真正的解决方案,忽略一个文件上的每个警告对您的项目来说是一个非常糟糕的决定。
【解决方案2】:

什么警告导致“未找到实例方法”?

那是-Wobjc-method-access,所以试试

#pragma GCC diagnostic ignored "-Wobjc-method-access"

或使用-Wno-objc-method-access 编译该文件以仅抑制该警告。

上述两种解决方案都有其适用于整个文件的限制,这通常不是您想要的。 clang 为您提供更好的选择:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-method-access"
if (sampleRate > 0 && ![self isFinishing])
{
    return self.progress;
}
#pragma clang diagnostic pop

第一个编译指示将所有当前警告标志保存到内部堆栈,然后将这个警告设置为忽略以使代码跟随,在该代码之后,最后一行将弹出保存的状态,从而再次恢复所有警告标志.

请注意,您收到这样的警告意味着您的代码有问题。要么这个方法真的不存在,在那种情况下你真的不应该调用它,要么它会在运行时存在,你只是忘记告诉编译器了。

首先,您应该确保代码安全,因为调用不存在的方法通常会使您的应用崩溃:

if (sampleRate > 0 
    && ([self respondsToSelector:@selector(isFinishing)] 
        && ![self isFinishing]
    )
) {
    return self.progress;
}

此代码首先测试调用isFinishing 是否正常或相当致命。只有在没有问题的情况下才会实际执行调用。

现在编译器仍然需要知道isFinishing 方法,不仅仅是它存在,还需要知道它返回什么。对于返回 bool、返回整数、返回 double 或返回对象(或任何其他类型的指针)的方法,![self isFinishing] 的机器代码不一定相同。只有知道该方法的原型,编译器才能生成正确的代码。最简单的方法是为此使用属性。如果您不想在头文件(.h 文件)中公开该属性,可以在源文件(.m 文件)中声明该属性,只需在类扩展名中声明它(这基本上是一个未命名的类别):

@interface YourClass ( )
    @property (readonly) BOOL isFinishing;
@end

@implementation YourClass
// Implementation of the class follows here

现在编译器知道isFinishing 返回一个BOOL。为了避免编译器为该属性生成任何代码,您将其放入实现中:

@dynamic isFinishing;

这告诉编译器不要为该属性做任何事情(不要创建 ivar,不要创建 getter)并假设在运行时会存在名为 isFinishing 的方法(编译器不会生成任何在运行时检查的代码,它相信你的话!)

【讨论】:

    【解决方案3】:

    好的,我又来了 :) 我尝试了各种“clang”特定的#pragmas,但没有任何效果,我唯一能想到的就是在实际 使用方法,因此:

    main.m:

    #import <Foundation/Foundation.h>
    #import "PragmaTest.h"
    
    @interface PragmaTest ()
    
        - (void)noSuchMethod;
    
    @end
    
    
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
    
            PragmaTest *pragmaTest = [[PragmaTest alloc] init];
    
            #pragma clang diagnostic push
            #pragma clang diagnostic ignored "-Wall"
    
            [pragmaTest noSuchMethod];
    
            #pragma clang diagnostic pop
    
            [pragmaTest release];
    
            // insert code here...
            NSLog(@"Hello, World!");
    
        }
        return 0;
    }
    

    PragmaTest.h:

    #import <Foundation/Foundation.h>
    
    @interface PragmaTest : NSObject
    
    @end
    

    PragmaTest.m:

    #import "PragmaTest.h"
    
    @implementation PragmaTest
    
    - (void)noSuchMethod
    {
        NSLog(@"noSuchMethod");
    }
    
    @end
    

    我希望这符合您的要求,虽然它不是涉及 #pragmas 的解决方案,但我希望您不会觉得有必要否决一个有用的答案。

    【讨论】:

      【解决方案4】:

      这是您可以抑制警告的方法。这在您只想实现类的几个方法而不需要其余部分的测试(假)类中特别有用。

      #pragma clang diagnostic push
      #pragma clang diagnostic ignored "-Wincomplete-implementation"
      
      @implementation MyClass
      
      
      @end
      
      #pragma clang diagnostic pop
      

      【讨论】:

        【解决方案5】:

        Pavan 的链接很好,但也可能有一个简单更明显的答案。您的 isFinishing 方法是否在您的 .m 文件中,但在使用后声明(在哪里收到警告)?如果是这样,请将声明移到使用之前。 如果那个简单的案例不是您可能想要的答案,您可以使用一个类别让编译器知道这个方法。我经常这样做是为了对“私有”方法进行单元测试。 另一种选择是为此文件使用编译器标志来抑制整个文件的此警告。 我知道这些都没有指定如何使用编译指示解决这个问题,但您可能会找到另一种可行的解决方案。

        【讨论】:

          猜你喜欢
          • 2011-12-28
          • 2018-02-04
          • 2011-02-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多