Search code examples
cocoa-touchcocoansassert

Why NSAssert1, etc instead of NSAssert?


I thought NSAssert couldn't use printf specifiers, but this:

NSAssert(0, @"%@%@", @"foo", @"bar");

works just as you'd expect:

*** Assertion failure in -[MyClass myMethod], <Path>/MyClass.m:84
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
    reason: 'foobar'

So what's the point of using NSAssert1, NSAssert2, etc when NSAssert works?

This with Xcode 4.0 and the iOS 4.3 SDK, if that matters. (If it doesn't, I'll update the tags.)


Solution

  • Current versions of NSAssert() use preprocessor variadic macros, i.e., __VA_ARGS__. Since variadic macros are a C99 feature, my guess is that older versions of the SDK didn’t allow variable arguments in NSAssert(), hence the need for NSAssert1(), NSAssert2(), etc.

    If you try to compile

    NSAssert(0, @"%@%@", @"foo", @"bar");
    

    using -std=c89 or -ansi (ISO C90, an older version of C that doesn’t support variadic macros), you get a compiler error:

    error: too many arguments provided to function-like macro invocation
        NSAssert(0, @"%@%@", @"foo", @"bar");
    

    For that code to compile with -std=c89 or -ansi, you need to use NSAssert2():

    NSAssert2(0, @"%@%@", @"foo", @"bar");