Xcode Warnings: Turn Them Up to Eleven

December 11, 2014 — 5 Comments

What if there were a way to get feedback on your code every time you compiled?

This Is Spinal Tap: “These go to eleven.”

As developers, we depend on feedback to tell us how good our code is. That’s why I’m passionate about unit tests and TDD: they give me feedback quickly, and the feedback is so good that I’ve come to depend on it. Unit tests are faster than manual testing, and faster than acceptance testing. But there are forms of feedback that are faster still…

I’ve seen crashers ship which could have been prevented altogether, simply by enabling more compiler warnings. The sooner you detect a problem, the cheaper it is to find and fix. So let’s all dial up our Xcode warnings to catch more problems at compile time. …But how high should the warning settings be?

[This post is part of the series TDD Sample App: The Complete Collection …So Far]

First, get to zero

Before you increase your Xcode warnings, drive any existing warnings down to zero. Fix the problems where you can. Where it’s too much, disable that particular warning for now.

You don’t want noise that hides useful information. If you put up with a list of “the usual warnings,” you won’t notice when a particularly serious one creeps into the list. This also applies if you use #pragma warning, or have a script that flags TODO as a warning — you’re just adding noise. Get to zero.

Turn up Xcode warnings as high as you can stand them

Once you have a clean slate, start enabling more Xcode warnings. Do this at the project level so that it applies across all your targets. Gradually turn it “up to eleven,” rebuilding after each setting change.

Some warnings will be excessive for your codebase. Others simply don’t work well with Apple’s frameworks. Don’t worry about those, just keep going down the list. Check out Peter Hosey’s excellent description of the warnings he uses.

When you reach the bottom of the “Warnings” sections, skip over a few sections and do the “Static Analyzer” sections as well.

XcodeWarnings: An xcconfig for easier set-up

Click-click-clicking through a new project to turn on all these Xcode warnings is a pain. I made an xcconfig to make life easier, called XcodeWarnings.

XcodeWarnings

To add XcodeWarnings.xcconfig to your project, drag it in. Where it prompts “Add to targets,” deselect all targets. (Otherwise, it will be included in the bundle.)

If you don’t have a previous xcconfig, click on your project Xcode’s Navigator pane. In the main editing area, select your project, and select the Info tab. For each of your configurations, select XcodeWarnings at the project level:

Specify XcodeWarnings as configuration

(If you do have a previous xcconfig, then edit it to #include "XcodeWarnings.xcconfig".)

Whether you add XcodeWarnings as the root xcconfig or #include it from another one, it’s time to clear out any overrides to let the xcconfig take control. Still at the project level, select the Build Settings tab. Find your way down to the first section of Xcode warnings, labeled Apple LLVM x.0 – Warning Policies. Click the first entry:

Xcode warnings settings

Then scroll down through the various Xcode warning sections. When you reach the last one, shift-click the last entry. This should select all the warning settings. Press delete. This will clear the project-level overrides, causing the settings to fall back to what the xcconfig specifies.

Do the same for the static analyzer settings. Keep scrolling down and find the section labeled Static Analyzer – Analysis Policy. Again, click the first setting, then scroll to the last static analyzer section. Shift-click the last entry, and press delete.

…That may sound complicated, but it takes longer to describe than to do!

Once you clear the overrides, XcodeWarnings.xcconfig will be in full effect. If you’re starting a new project, you’re all set. But if you’ve added this to an existing project and rebuilt, you may have a large pile of warnings. Start by commenting out specific lines in XcodeWarnings.xcconfig (use ⌘-/) until you are back to zero.

Then one at a time: Take a line you commented out and hit ⌘-/ to bring that setting back into play. Rebuild, and decide what to do. Either:

  • Fix the problems, or
  • Comment it back out.

-Weverything is too much for me

There is another approach to turning warning settings “up to eleven”, and that’s to specify -Weverything in “Other Warning Flags”. This turns on all the visible Xcode warnings, along with other Clang compiler warnings that Apple has not made visible in the Xcode project settings.

Because -Weverything is so strong, people usually add other flags to turn off some of those extra Clang warnings.

If that works for you, great. Personally, -Weverything is too much for me. I get frustrated with the invisible nature of those hidden warning settings. So I prefer XcodeWarnings.xcconfig where everything is explicitly listed.

Get that feedback any way you can

Remember, this is all about getting feedback on your code to catch problems early. As long as you turn your settings up to eleven, it probably doesn’t matter how you do it — as long as you do it. Try XcodeWarnings and see if it helps you. Turn up the warnings, drive them to zero, then stay at zero!

Question: Which Xcode warnings do you enable? Which do you disable? Do you use any of those hidden Clang warnings? You can leave a comment by clicking here.

Did you find this useful? Subscribe today to get regular posts on clean iOS code.

[This post is part of the series TDD Sample App: The Complete Collection …So Far]

Jon Reid

Posts Twitter Facebook Google+

I've been practicing Test Driven Development (TDD) since 2001. Learn more on my About page.

5 responses to Xcode Warnings: Turn Them Up to Eleven

  1. Thanks for this!
    So I used your XcodeWarnings file and I had about 50 warnings popup for “weak property may be unpredictably set to nil”
    My question is how are we supposed to handle buttons and other objects in our storyboard that when referenced in code are weak

    there are many places in my code where I am hiding or unhiding multiple objects on the screen. Should I be really doing this for every one of them:
    > viewcontroller.someButton.hidden = True;
    changed to:
    >Uibutton *strongButton = viewcontroller.someButton
    >if(strongButton){ strongButton.hidden = true;}

    or is there a better way to do this?

    • Prasanth, this warning makes sense for various other weak properties, where you don’t really know when something might disappear out from underneath you. But for view outlets… I just make them strong, since viewDidUnload is no longer relevant.

      The other way is to say, “oh well,” and disable that warning.

  2. I think the best approach is to start with -Weverything for warnings, treat warnings as errors is fundamental too, then proceed analyzing the warnings with the rest of the team and agree which ones to silence in the Xcode build settings.
    The warnings we ignore in the build settings (having -Weverything turned on) are: -Wno-pedantic -Wno-objc-missing-property-synthesis -Wno-selector -Wno-old-style-cast.

    In some cases, properties defined by a protocol, trying to implement custom setters and getters gets you Xcode complaining about accessing ivars directly even though you are completely within your rights to do so. In this case a good

    #pragma clang diagnostic push IGNORE_EXTRA_WARNINGS
    #pragma clang diagnostic ignored “”
    […]
    #pragma clang diagnostic pop IGNORE_EXTRA_WARNINGS

    will do the trick.

  3. Any tips for getting the XcodeWarnings.xcconfig file to play nice when using Cocoapods?

    The Pods.debug.xcconfig / Pods.release.xcconfig files are generated so there is no easy way to #include XcodeWarnings.xcconfig in them. I can go the other direction and #include “Pods/Target Support Files/Pods/Pods.debug.xcconfig” in the XcodeWarnings.xconfig, but I can’t find a way to conditionally include the release flavor for the release configuration. I tried this, but it’s invalid:

    #ifdef DEBUG
    #include "Pods/Target Support Files/Pods/Pods.debug.xcconfig"
    #else
    #include "Pods/Target Support Files/Pods/Pods.release.xcconfig"
    #endif

    The other problem with this is that specifying a different base configuration generates a warnings on every pod update command (see https://github.com/CocoaPods/CocoaPods/issues/2633).

    Anyway, as much as I like the idea of using a xcconfig file to control warnings, this seems a bit awkward if using CocoaPods. Please let me know if I have missed something.

    –Mark

Leave a Reply

Text formatting is available via select HTML.

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

*