Reputation: 779
I can't figure out why I get
use of undeclared identifier _cmd did you mean rcmd
on the line where NSAssert is.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int x = 10;
NSAssert(x > 11, @"x should be greater than %d", x);
[pool drain];
return 0;
}
Upvotes: 49
Views: 6336
Reputation:
TL;DR - stick with stray NSAssert() - don't try this in production
Original code
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int x = 10;
NSAssert(x > 11, @"x should be greater than %d", x);
[pool drain];
return 0;
}
Build failure
Compiling file hello.m ...
hello.m:9:5: error: use of undeclared identifier '_cmd'
NSAssert(x > 11, @"x should be greater than %d", x);
^
/usr/include/Foundation/NSException.h:450:32: note: expanded from macro 'NSAssert'
handleFailureInMethod: _cmd \
^
hello.m:9:5: error: use of undeclared identifier 'self'
/usr/include/Foundation/NSException.h:451:17: note: expanded from macro 'NSAssert'
object: self \
^
2 errors generated.
Based on explanation by @hooleyhoop @Robert and
id
self
SEL,
the following dirty hack may be applicable if I insist on using
NSAssert()
instead of
NSCAssert()
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int x = 10;
// Dirty hack
SEL _cmd=NULL;
NSObject *self=NULL;
NSAssert(x > 11, @"x should be greater than %d", x);
[pool drain];
return 0;
}
Build & run
Compiling file hello.m ...
Linking tool hello ...
2021-03-04 21:25:58.035 hello[39049:39049] hello.m:13 Assertion failed in (null)(instance), method (null). x should be greater than 10
./obj/hello: Uncaught exception NSInternalInconsistencyException, reason: hello.m:13 Assertion failed in (null)(instance), method (null). x should be greater than 10
Hooray it works! But, alas, please stay away from it :)
Upvotes: 0
Reputation: 9198
Inside every Objective-c method there are two hidden variables id self
and SEL _cmd
so
- (void)foo:(id)bar;
is really
void foo(id self, SEL _cmd, id bar) { ... }
and when you call
[someObject foo:@"hello world"]
it is actually
foo( someObject, @selector(foo), @"hello world")
If you cmd-click on NSAssert to jump to it's definition you will see that it is a macro that uses the hidden _cmd variable of the method you are calling it from. This means that if you are not inside an Objective-c method (perhaps you are in 'main'), therefore you don't have a _cmd argument, you cannot use NSAssert.
Instead you can use the alternative NSCAssert.
Upvotes: 113
Reputation: 19867
NSAssert
is only meant to be used within Objective-C methods. Since main
is a C function, use NSCAssert
instead.
Upvotes: 31
Reputation: 1528
Try to replace
NSAssert(x > 11, [NSString stringWithFormat:@"x should be greater than %d", x]);
with
NSCAssert(x > 11, [NSString stringWithFormat:@"x should be greater than %d", x]);
Upvotes: 1
Reputation: 8147
You have to wrap your string in a NSString class if you want to use format parameters. That is because @""
is a default constructor for a plain NSString. The way it is written now gives a third parameter to the NSAssert
function and messes with it.
NSAssert(x > 11, [NSString stringWithFormat:@"x should be greater than %d", x]);
Upvotes: 0