如何在objective-C中使用可变方法定义宏?

Mat*_*ham 2 macros objective-c variadic ios

我试图打电话的方法是;

- (void)addLogWithLevel:(MDCLogLevel)logLevel logContent:(NSString *)logContent, ...
{
    va_list args;
    va_start(args, logContent);
    NSString *message = [[NSString alloc] initWithFormat:logContent
                                               arguments:args];
    va_end(args);
    MDCLog *log = [MDCLog logWithContent:message content:logLevel];
    [self.deviceLogs addObject:log];
}
Run Code Online (Sandbox Code Playgroud)

我已经将宏定义为;

#define MDCLogDebug(format, ...) [[MDCLogController sharedController] addLogWithLevel:MDCLogLevelDebug logContent:(__VA_ARGS__)];
Run Code Online (Sandbox Code Playgroud)

我尝试过这种宏的各种格式,但似乎没有任何效果.

如果我打电话;

MDCLogDebug(@"Test:%@", @"Hey");
Run Code Online (Sandbox Code Playgroud)

我在控制台中看到的只是;

我哪里错了?我是使用Variadic方法的新手,我的C不是那么棒!

Ali*_*are 10

实际上,你的问题并不直接与Objective-C有关,而是与C本身有关,因为宏是普通的C预处理器指令.

在宏中,__VA_ARGS__表示放置的参数而不是....

所以在你的调用中MDCLogDebug(@"Test:%@", @"Hey"),format参数是@"Test:%@"并且之后__VA_ARGS__表示其余的参数,即仅仅@"Hey"在你的情况下.

如果你想传递@"Test:%@"@"Hey"作为参数logContent:,你必须明确告诉它,使用:

#define MDCLogDebug(format, ...) [[MDCLogController sharedController] addLogWithLevel:MDCLogLevelDebug logContent:format, __VA_ARGS__]
Run Code Online (Sandbox Code Playgroud)

注意:一个更好的解决方案是使用##前面的前缀,__VA_ARGS__这样如果__VA_ARGS__为空则不会添加逗号(即如果你只传递一个format参数但之后没有,就像MDCLogDebug(@"Foo")):

#define MDCLogDebug(format, ...) [[MDCLogController sharedController] \
                                  addLogWithLevel:MDCLogLevelDebug \
                                       logContent:format, ## __VA_ARGS__]
Run Code Online (Sandbox Code Playgroud)

(注意:我在上面的最后一个宏定义中使用反斜杠,允许宏写在多行上,而不是写在一个大的长行上)

有关更多信息,请参阅此处有关Variadic宏的官方GCC文档.

  • 我认为`logContent:(format,__ VA_ARGS __)`中的括号是错误的.它应该是`#define MDCLogDebug(format,...)[[MDCLogController sharedController] addLogWithLevel:MDCLogLevelDebug logContent:format,## __ VA_ARGS __]`.并且你不应该在宏定义中附加分号! (2认同)