I wonder if it\'s a good habit to use NSAssert all over the place? What would be the benefit of doing that? In which situations is it a good idea to use it?
Broad use of NSAssert()
will not turn ObjC into Eiffel, but it's still a fairly good practice as long as you keep in mind how it's actually implemented and what it's doing. Things to keep in mind about NSAssert()
:
Xcode does not turn off NSAssert()
in Release mode by default. You have to remember to add NS_BLOCK_ASSERTIONS
to GCC_PREPROCESSOR_DEFINITIONS
in you xcconfig. (You are using xcconfigs, right?) A common issue is to assert non-nil in cases where nil will quietly work; this can mean field crashes for things that could have gracefully recovered. This is unrelated to the NDEBUG
macro used by assert()
, and you have to remember to define both if your code includes both types of assertions.
If you compile out NSAssert()
in Release mode, then you get no indication where a problem happened when customers send you their logs. I personally wrap NSAssert()
in my own macros that always log, even in Release mode.
NSAssert()
often forces duplicated logic. Consider the case of testing a C++ pointer for NULL. You use NSAssert()
, but you still need to use a simple if()
test as well to avoid crashing in the field. This kind of duplicated code can become the source of bugs, and I have seen code that fails due to assertions that are no longer valid. (Luckily this is generally in Debug mode!) I have debated a lot how to create a macro that would combine the assertion and if()
, but it's hard to do without being fragile or making the code hard to understand.
Because of the last issue, I typically put "NSAssert(NO, ...)
" in an else{}
clause rather than performing assertion at the top of the method. This is not ideal because it moves the contract away from the method signature (thus reducing its documentary benefit), but it is the most effective approach I've found in practice.