奇怪的错误NSAssert

时间:2012-03-16 14:49:34

标签: objective-c nsassert

我无法弄清楚为什么会得到

use of undeclared identifier _cmd  did you mean rcmd

在NSAssert所在的行上。

#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;
}

5 个答案:

答案 0 :(得分:103)

在每个Objective-c方法中,有两个隐藏变量id selfSEL _cmd

所以

- (void)foo:(id)bar;

真的是

void foo(id self, SEL _cmd, id bar) { ... }

当你打电话

[someObject foo:@"hello world"]

实际上是

foo( someObject, @selector(foo), @"hello world")

如果你cmd-单击NSAssert跳转到它的定义,你会发现它是一个宏,它使用你调用它的方法的隐藏_cmd变量。这意味着如果你不在Objective-c方法中(也许你在'main'中),因此你没有_cmd参数,你就不能使用NSAssert。

相反,您可以使用替代NSCAssert。

答案 1 :(得分:30)

NSAssert is only meant to be used within Objective-C methods。由于main是C函数,请改用NSCAssert

答案 2 :(得分:1)

尝试替换

NSAssert(x> 11,[NSString stringWithFormat:@&#34; x应大于%d&#34;,x]);

NSCAssert(x> 11,[NSString stringWithFormat:@&#34; x应大于%d&#34;,x]);

答案 3 :(得分:0)

如果要使用格式参数,则必须将字符串包装在NSString类中。这是因为@""是普通NSString的默认构造函数。它现在的编写方式为NSAssert函数提供了第三个参数,并与之混淆。

NSAssert(x > 11, [NSString stringWithFormat:@"x should be greater than %d", x]);

答案 4 :(得分:0)

TL;DR - 坚持使用流浪 NSAssert() - 不要在生产中尝试这个

原始代码

#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;
}

构建失败

 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.

基于 explanation by @hooleyhoop @Robertid self SEL, 如果我坚持使用以下肮脏的黑客可能适用 NSAssert() 而不是 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;
}

构建和运行

 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

万岁它有效!但是,唉,请远离它:)