Pragmas Aren’t Just For Marks
Ask an iOS developer what a #pragma
is and more times than not they’ll tell you, “It’s a directive that lets you group your functions in XCode’s method index thingy.” OK, I confess, that’s what my answer would’ve been not too long ago!
The truth is, there are plenty of #pragma
usages out there and some of the more low-level minded developers use them quite a bit! In many cases, they can be abused and make reading source code a real downer, but let’s review some of the more useful ones and embiggen ourselves. :-)
NOTE: This blog will only refer to the Clang compiler (LLVM) and not GCC, though some of it still applies. Since I don’t see any reason to be using GCC anymore, I’m not going to explicitly talk about it.
Explicit warnings and errors
The compiler is a robot; it will mark what’s wrong with your code using a set of rules that’ve been defined by Clang. But, every so often you’re smarter than it. Often, you might find some offending code that you know will lead to problems but, for whatever reason, can’t fix yourself at the moment. You can explicitly signal errors like this:
- (NSInteger)divide:(NSInteger)dividend by:(NSInteger)divisor { #error Whoa, buddy, you need to check for zero here! return (dividend / divisor); }
You can signal warnings similarly:
- (float)divide:(float)dividend by:(float)divisor { #warning Dude, don't compare floating point numbers like this! if (divisor != 0.0) { return (dividend / divisor); } else { return NAN; } }
These warnings and errors will show up in XCode’s Issue Navigator like any other warning and error:
The alternative is running a git blame
and emailing the developer, but it might take too much time and it’s nicer to signal the issue right where the code is. I’ve even seen developers mark these warnings when writing their own code as a reminded to change the code later. Use it however it’s most useful to you and your team.
Oh, and strictly speaking, this isn’t a #pragma
, but it’s in the same family and #pragma message behaves the same way as #warning
.
Temporarily disable a compiler behavior
While most iOS developers don’t futz around much with compiler options, it’s these options which control how strictly to check (or not check) your code for errors. Sometimes, though, you want to make an exception…just once. The best way to do this to put your offending code on an island with no law.
Here’s something I ran into with InnerBand: When you use ARC, the compiler inserts memory-management calls for you. There are cases, though, where it can get confused. One such case is when you use NSSelectorFromString
to have a dynamically-named selector called. Since ARC can’t know what the method will be and what kind of memory management to use, you’ll be warned with something like, “performSelector may cause a leak because its selector is unknown”.
If you know your code won’t leak, you can suppress the warning for just this instance by wrapping it like this:
#pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [myObj performSelector:mySelector withObject:name]; #pragma clang diagnostic pop
Note how we disable the -Warc-performSelector-leaks
check by pushing and popping the change around our code. This assures us we don’t disable it globally, which would be a huge mistake.
There’s a large number of options you can disable if need be, but you’ll have to consult The Clang User’s Manual to learn about all of them.
Suppressing warnings for unused variables
It’s useful to be told that a variable you’ve defined is going unused. In most cases, you want to remove these references to improve performance (however slightly), but sometimes you want to keep them. Why? Perhaps they have a future usage or the functionality is only temporarily removed. Either way, you can suppress the warning with #pragma unused
:
- (void)giveMeFive { NSString *foo; #pragma unused (foo) return 5; }
Now you can keep your code in place without the compiler complaining about it. And yes, that pragma needs to go below the offending code.
Conclusion
Pragma are there to help you, but don’t abuse them. Looking at code loaded up with preprocessing code and pragmas is like reading code with gotos, a total headache. Use them appropriately!
InnerBand Tutorial Part 3: The Magical Message Center Tutorial: Using RaptureXML Like A Pro!
Comments are currently closed.