在宏中使用 Objective C API 登录静态库
Posted
技术标签:
【中文标题】在宏中使用 Objective C API 登录静态库【英文标题】:Using Objective C API in Macro to Log in static lib 【发布时间】:2016-01-27 12:27:54 【问题描述】:我想做这样的事情,但在第一个“if”时出错。
#if ([[[NSProcessInfo processInfo] arguments] containsObject:@"-com.myproj.MyLibDebug"])
#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define DLog(...) /* */
#endif
如何使用宏来使用它?是否可以在 Objective C 中编写这样的表达式?
或者做一些更高级的事情,比如
在参数数组中获取-com.myproj.MyLibDebug
的下一个值,然后根据值将调试日志级别设置为 4 或 8。
从构建配置(方案)传递的参数是
-com.myproj.MyLibDebug 4
【问题讨论】:
任何反对票都应该解释。 【参考方案1】:我会反过来,将定义基于 if() 结果。
#define DLog(fmt, ...) if ([[[NSProcessInfo processInfo] arguments] containsObject:@"-com.myproj.MyLibDebug"]) \
....\
else \
#if
是基于宏的,它不能使用动态值
【讨论】:
...所以问题是什么?混合编译时和运行时元素?您还愿意评论一下该宏所产生的费用吗? 是的,问题是宏是在编译时评估的,而不是在运行时评估的,因此无法对参数数组进行评估。至于复杂性/时间开销,预处理器将使用if()
块更改每次出现的DLog()
。不过,我不是宏观问题的专家。
谢谢。这似乎更好或将起作用。但要获得这些值,我最好有一个新的 Logger 类,它将解码和使用 NSLog。这个问题然后我可以打印出消息,但松开 LINE 和 FILE 宏。不是吗?
您可以使用将_LINE_
和_FILE_
用作参数的宏。我建议你看看 cocoalumberjack 来处理日志部分,我发现它非常有用且可定制。【参考方案2】:
我不能使用 MACRO 进行这种日志记录,而是使用我自己的类来记录它,因为我必须从启动时传递的参数中解码运行时 logLevel。这是我的课。
头文件。
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, IDCLogFlag)
IDCLogFlagError = (1 << 0),
IDCLogFlagWarning = (1 << 1),
IDCLogFlagInfo = (1 << 2),
IDCLogFlagDebug = (1 << 3),
IDCLogFlagVerbose = (1 << 4)
;
typedef NS_ENUM(NSUInteger, IDCLogLevel)
IDCLogLevelOff = 0,
IDCLogLevelError = IDCLogFlagError,
IDCLogLevelWarning = IDCLogFlagError | IDCLogFlagWarning,
IDCLogLevelInfo = IDCLogLevelWarning | IDCLogFlagInfo,
IDCLogLevelDebug = IDCLogLevelInfo | IDCLogFlagDebug,
IDCLogLevelVerbose = IDCLogLevelDebug | IDCLogFlagVerbose,
IDCLogLevelAll = NSUIntegerMax
;
@interface IDCLogger : NSObject
/** Programmatically set the log level.*/
+ (void)setLogLevel:(int)l;
+(void)error:(NSString *)format, ... ;
+(void)warn:(NSString *)format, ... ;
+(void)info:(NSString *)format, ... ;
+(void)debug:(NSString *)format, ... ;
+(void)verbose:(NSString *)format, ... ;
@end
.m 文件
#import "IDCLogger.h"
static NSUInteger logLevel = IDCLogLevelError;
/** This argument should be passed from XCode's build scheme configuration option, Arguments passed on launch */
static const NSString *kIdcLogLevelArgument = @"-com.yourcompany.IDCLogLevel";
@implementation IDCLogger
+ (instancetype)sharedInstance
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
sharedInstance = [[self alloc] init];
);
return sharedInstance;
+(void)initialize
NSArray *arguments = [[NSProcessInfo processInfo] arguments];
NSUInteger value = 1;
if ([arguments containsObject:kIdcLogLevelArgument])
NSUInteger index = [arguments indexOfObject:kIdcLogLevelArgument];
if (arguments.count > index)
NSString *valueStr = [arguments objectAtIndex:index + 1];
NSCharacterSet* notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([valueStr rangeOfCharacterFromSet:notDigits].location == NSNotFound)
value = [valueStr integerValue];
logLevel = value;
// NSUInteger exp = 0;
// if (value > 0)
// exp = log2(value) + 1;
//
// logLevel = pow(2, exp);
// NSLog(@"logLevel = %lu", (unsigned long)logLevel);
+ (void)setLogLevel:(int)l
logLevel = l;
NSLog(@"[%@] Log level set to: %i", [self class], l);
+(void)error:(NSString *)format, ...
if (logLevel >= IDCLogLevelError)
va_list args;
va_start(args, format);
[[self sharedInstance] logFormat:format withParameters:args];
va_end(args);
+(void)warn:(NSString *)format, ...
if (logLevel >= IDCLogLevelWarning)
va_list args;
va_start(args, format);
[[self sharedInstance] logFormat:format withParameters:args];
va_end(args);
+(void)info:(NSString *)format, ...
if (logLevel >= IDCLogLevelInfo)
va_list args;
va_start(args, format);
[[self sharedInstance] logFormat:format withParameters:args];
va_end(args);
+(void)debug:(NSString *)format, ...
if (logLevel >= IDCLogLevelDebug)
va_list args;
va_start(args, format);
[[self sharedInstance] logFormat:format withParameters:args];
va_end(args);
+(void)verbose:(NSString *)format, ...
if (logLevel >= IDCLogLevelVerbose)
va_list args;
va_start(args, format);
[[self sharedInstance] logFormat:format withParameters:args];
va_end(args);
/** log the message formatted with status*/
-(void) log:(NSString*)format, ...
va_list args;
va_start(args, format);
va_end(args);
NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
NSLog(@"%@", str);
[str release];
-(void) logFormat:(NSString *)format withParameters:(va_list)valist
NSString *str = [[NSString alloc] initWithFormat:format arguments:valist];
NSLog(@"%@", str);
[str release];
@end
测试代码
- (void)testLogger
[IDCLogger error:@"Error"];
[IDCLogger warn:@"Warning"];
[IDCLogger info:@"Info"];
[IDCLogger debug:@"Debug"];
[IDCLogger verbose:@"Verbose"];
NSDate *d = [NSDate date];
int i = 123;
[IDCLogger error:@"Error with params. %i, %@", i, d];
[IDCLogger warn:@"Warning with params. %i, %@", i, d];
[IDCLogger info:@"Info with params. %i, %@", i, d];
[IDCLogger debug:@"Debug with params. %i, %@", i, d];
[IDCLogger verbose:@"verbose with params. %i, %@", i, d];
[IDCLogger setLogLevel:0]; // no logging
[IDCLogger error:@"Error with params. %i, %@", i, d];
[IDCLogger warn:@"Warning with params. %i, %@", i, d];
[IDCLogger info:@"Info with params. %i, %@", i, d];
[IDCLogger debug:@"Debug with params. %i, %@", i, d];
[IDCLogger verbose:@"verbose with params. %i, %@", i, d];
[IDCLogger setLogLevel:UINT_MAX]; // All logging
[IDCLogger error:@"Error with params. %i, %@", i, d];
[IDCLogger warn:@"Warning with params. %i, %@", i, d];
[IDCLogger info:@"Info with params. %i, %@", i, d];
[IDCLogger debug:@"Debug with params. %i, %@", i, d];
[IDCLogger verbose:@"verbose with params. %i, %@", i, d];
[IDCLogger setLogLevel:IDCLogLevelDebug]; // value = 15, error, warn, info and debug log
[IDCLogger error:@"Error with params. %i, %@", i, d];
[IDCLogger warn:@"Warning with params. %i, %@", i, d];
[IDCLogger info:@"Info with params. %i, %@", i, d];
[IDCLogger debug:@"Debug with params. %i, %@", i, d];
[IDCLogger verbose:@"verbose with params. %i, %@", i, d];
【讨论】:
以上是关于在宏中使用 Objective C API 登录静态库的主要内容,如果未能解决你的问题,请参考以下文章
MS Visual Studio 2010 C++ 预处理器 - 如果函数在宏中定义并在其他地方调用,未定义时是不是有任何开销