Using #pragma to suppress “Instance method not found” warnings in Xcode

拈花ヽ惹草 提交于 2019-12-18 02:54:11

问题


I want to use #pragma (in Xcode) to suppress the warning:

warning: instance method '-someMethod' not found (return type defaults to 'id')

I've tried:

#pragma GCC diagnostic ignored "-Wmissing-declarations"

And several others, but nothing works.

What warning causes the "instance method not found"?

Edit

As requested here is the actual code:

...

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

...

And the build log output:

/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])
                            ^~~~~~~~~~~~~~~~~~

回答1:


See: https://stackoverflow.com/a/34043306/89035 for a #pragma to suppress "instance method not found" warnings.

While it seem that a true #pragma solution to this does not exist turning off the warnings in individual files can be accomplished by use of the -w switch.

NB: This solution is for Xcode 4.2 and above

  1. Select the target
  2. Click on the "Build Phases" tab
  3. Under "Compile Sources" add the -w switch to the file(s) you wish to suppress warnings on




回答2:


What warning causes the "instance method not found"?

That's -Wobjc-method-access, so try

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

or compile that file with -Wno-objc-method-access to only suppress that warning.

Both solutions above have the limitation that they will apply to the whole file, which is usually not what you want. clang offers you an even better alternative:

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

The first pragma saves all current warning flags to an internal stack, then you set this one warning to ignored for the code to follow and after that code, the last line will pops the saved state and thus restore all the warnings flags again.

Note that the fact that you get such a warning at all means something is fishy about your code. Either this method really doesn't exist, in that case you really shouldn't call it, or it will exist at runtime, you just forgot to tell the compiler about that.

First you should make your code safe because calling a non-existing method will usually crash you app:

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

This code first tests if calling isFinishing is okay or rather fatal. Only if it is okay the call is actually performed.

Now the compiler still needs to know about the method isFinishing, not just that it exists but also what it returns. The machine code for ![self isFinishing] is not necessarily the same for a method returning a bool, returning an integer, returning a double or returning an object (or any other kind of pointer). The compiler can only generate correct code if it knows the prototype of that method. The easiest way is to use a property for that. You can declare that property in your source file (the .m file) if you don't want to expose it in your header file (the .h file), just declare it in a class extension (that's basically an unnamed category):

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

@implementation YourClass
// Implementation of the class follows here

Now the compiler knows that isFinishing returns a BOOL. And to avoid that the compiler generates any code for that property, you put that into the implementation:

@dynamic isFinishing;

This tells the compiler to not do anything for that property (don't create an ivar, don't create a getter) and just assume that at runtime a method named isFinishing will exist (the compiler will not make any code to check at runtime, it trusts your word!)




回答3:


OK, me again :) I tried various 'clang' specific #pragmas but nothing worked, and only thing I could think of was to declare the method as a 'private method' from within the class that actually uses the method, thus:

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

I hope this meets your requirements and although it's not a solution involving #pragmas I hope you won't feel the need to downvote a helpful answer.




回答4:


Pavan's link is good but there might also be a simple more obvious answer. Is your isFinishing method in your .m file but declared after its usage (where you get the warning)? If so, move the declaration before its usage. If that simple case is not the answer you might want you can use a category to let the compiler know about this method. I frequently do this to unit test "private" methods. Another option is to use a compiler flag for this file to suppress this warning for the entire file. I know none of those specify how to solve this with a pragma but you might find another solution viable.




回答5:


This is how you can suppress the warnings. This is especially useful in test (fake) classes where you want to implement only a few methods of a class and don't need the rest.

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincomplete-implementation"

@implementation MyClass


@end

#pragma clang diagnostic pop


来源:https://stackoverflow.com/questions/9310141/using-pragma-to-suppress-instance-method-not-found-warnings-in-xcode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!