Is there a way to propagate Interface Builder Conflicting Constraints errors to the rest of the build process and treat them as build errors?
Of course, the LLVM setting Treat Warnings as Errors
has no effect on Storyboard errors.
I have this view which clearly can't satisfy all constraints:
In Interface Builder:
These errors look like this:
Conflicting Constraints
Can't satisfy all constraints.
In the Xcode Project:
The errors are downgraded to warnings, so that the application compiles, builds, link and run.
How can I prevent the application to build if I have AutoLayout errors in a Storyboard in Interface Builder?
Here's, if not a complete solution, a few avenues to investigate.
First, note there are two main source of Auto Layout errors/warnings — unsatisfiable constraints and ambiguous constraints — and they get handled in different ways.
Also note that the full capability of Auto Layout can be exercised only at runtime — Xcode's tools offer some insight into what's going on with the constraints in a storyboard, but that's a bit different from what happens when those constraints are evaluated in a "real" view/window running in an app. ("Real" in quotes because the iOS simulator is just fine for layout debugging... it doesn't have to be a real device.)
ibtool
When Xcode "compiles" your storyboard as part of building your project, it delegates that function to the command line program ibtool
. While there doesn't seem to be a way to change how Xcode interprets ibtool
output (that is, to treat errors output by ibtool
as a reason to stop a build), you can invoke ibtool
an extra time yourself.
ibtool
to process your storyboard(s). Pass --warning
or --error
to get warning or error output. (Take a look at the build log for a normal build, and/or man ibtool
to see what other flags you might want.)exit
your shell script with a non-zero status code, and Xcode will halt the build.As noted, the real test of constraints is in a real layout situation, when your app runs. So a better time to catch constraint problems might not be as part of build automation, but in testing automation.
For ambiguous layout, you can detect things easily at runtime with the hasAmbiguousLayout
property on UIView
. And if you have a Boolean property you can query at runtime, you have the seed of something to put into automated testing. Just write some unit tests that run through your app's UI, test hasAmbiguousLayout
for important views, and fail whenever that property is true. Then your continuous integration system can tell you whenever somebody makes a commit that still builds, but breaks the post-commit unit tests.
For unsatisfiable layouts, it might be a little bit trickier. The Auto Layout system automatically logs to the console when it detects such problems, so you might be able to write a script for your CI system that looks for "Unable to simultaneously satisfy constraints" in the run logs from your unit testing. Alternately... I'm not sure if it's possible to run with specific Xcode debugger breakpoints active when executing tests through CI, but if it is, you can set a symbolic breakpoint on UIViewAlertForUnsatisfiableConstraints
.