可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm using Xcode 4.6 and I've got a header file which includes some constants I use throughout my code. I don't want to use preprocessor directives because I want them to be properly typed and such.
For example, I have this code in one of my .h files:
static NSString *kErrorCannotDivideByZero = @"Error: Cannot divide by zero";
and I use it in the corresponding .m file:
[self showToast:kErrorCannotDivideByZero];
I get the warning:
/path/to/my/headerFile.h:32:18: Unused variable 'kErrorCannotDivideByZero'
I know it's just a warning, but I've got about 50 of these warnings clogging up my compiler output.
Why am I getting this warning and how do I PROPERLY resolve it?
I'm not interested in simply suppressing all unused variable warnings, because I do want to get the legit ones.
回答1:
Make the declaration in your header extern
rather that static
. What you're doing is creating a variable for every translation unit that includes your header, and this is why Clang is warning you, because it is legitimately a defined variable that is not being used. The extern
keyword tells the compiler that the definition of the variable is found somewhere else (it might be in the same translation unit or it might be in another).
In your header, have:
// declare that the constant exists somewhere
extern NSString * const kErrorCannotDivideByZero;
And in one of your .m
files (typically the one that shares the same name as the header), put
// define the constant, i.e. this is where it exists
NSString * const kErrorCannotDivideByZero = @"Error: Cannot divide by zero";
Declaring variables extern
allows the compiler to ensure you are treating the variable correctly even if it doesn't know where it is defined (e.g. you can't use it as an NSArray
). The linker has the job of making sure you actually defined it somewhere.
回答2:
Clang will allow you to push and pop warning flags onto and from a "diagnostic" stack: "Controlling diagnostics via pragmas". You can wrap certain pieces of code like this:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
static NSString *kErrorCannotDivideByZero = @"Error: Cannot divide by zero";
#pragma clang diagnostic pop
to tell Clang that you know these aren't used, and that's okay in this particular instance.
Incidentally, you may not want to define these variables in a file that's being imported to many different places -- that's a good way to cause linker errors about variable redefinition (although this would only happen if the variable were globally linked -- declared/defined without static
). The usual pattern for constants like this is to put an extern
declaration in the header, and define the variable in another file. See Referencing a static NSString * const from another class for details.
As dreamlax has pointed out, you're actually getting these warnings because each file which imports your header is getting its own copy of the static
variable; when I suggested the #pragma
technique above, I was misunderstanding what you were asking for.
回答3:
Make your constants const
:
static NSString * const kErrorCannotDivideByZero = @"Error: Cannot divide by zero";
(and as others pointed out, use extern
and define in the implementation file)
回答4:
Perhaps, rather than initialising them to string literals, you could run an initialise function that loads these values from a locale-specific file so that errors are in a translated language. When your initialise function assigns to that variable, your compiler might be tempted to believe that the variable needs to exist for the compile to be successful.
回答5:
GCC (and I assume clang) don't warn about unused constants. One trap to look out for here is that pointers need to be const pointers, not just pointers to const; so, to properly declare an unused string constant that won't trigger any warnings, you need:
const char * const myConst = "myConst";
回答6:
You could move all the static variable declaration to your respective .m file. That should take away all those "unused variable" warnings. The reason being that static variables are limited to a file level scope.