nil in gdb is not defined as 0x0? - objective-c

I was stepping through some simple Objective-C code with gdb (inside of Xcode) and noticed something strange. Here is the relevant snippet:
NSString *s = nil;
int x = (s == nil);
As I'd expect, the value of x after these two lines is 1. Strangely, if I try something similar in gdb, it doesn't work the same:
(gdb) print ret
$1 = (NSString *) 0x0
(gdb) print (int)(ret==nil)
$2 = 0
(gdb) print nil
$3 = {<text variable, no debug info>} 0x167d18 <nil>
It seems like gdb has some definition for nil other than what objective-C uses (0x0). Can someone explain what's going on here?

When your code is being compiled, nil is a preprocessor constant defined to be either __null (a special GCC variable that serves as NULL), 0L, or 0:
<objc/objc.h>
#ifndef nil
#define nil __DARWIN_NULL /* id of Nil instance */
#endif
<sys/_types.h>
#ifdef __cplusplus
#ifdef __GNUG__
#define __DARWIN_NULL __null
#else /* ! __GNUG__ */
#ifdef __LP64__
#define __DARWIN_NULL (0L)
#else /* !__LP64__ */
#define __DARWIN_NULL 0
#endif /* __LP64__ */
#endif /* __GNUG__ */
#else /* ! __cplusplus */
#define __DARWIN_NULL ((void *)0)
#endif /* __cplusplus */
So, where does the nil that gdb picks up at runtime come from? You can tell from the message gdb gives that nil is the name of a variable located at that address:
(gdb) p nil
$1 = {<text variable, no debug info>} 0x20c49ba5da6428 <nil>
(gdb) i addr nil
Symbol "nil" is at 0x20c49ba5da6428 in a file compiled without debugging.
Its value, unsurprisingly, turns out to be 0:
(gdb) p *(long *)nil
$2 = 0
(gdb) x/xg nil
0x20c49ba5da6428 <nil>: 0x0000000000000000
Where does this variable come from? GDB can tell us:
(gdb) i shared nil
3 Foundation F - init Y Y /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation at 0x20c49ba5bb2000 (offset 0x20c49ba5bb2000)
Indeed, when we check the symbols defined in Foundation, we find nil:
$ nm -m /System/Library/Frameworks/Foundation.framework/Foundation | grep nil$
00000000001f4428 (__TEXT,__const) external _nil

It's pointing to the address in memory, not the variable contents.

Related

extern function with macro

Im having a linker problem in Objective C when i attempt to do a marco with a extern function. Any idea why?
Header file
To assist in doing comparison with the device version
extern NSString* getOperatingSystemVerisonCode();
#if TARGET_OS_IPHONE // iOS
#define DEVICE_SYSTEM_VERSION [[UIDevice currentDevice] systemVersion]
#else // Mac
#define DEVICE_SYSTEM_VERSION getOperatingSystemVerisonCode()
#endif
#define COMPARE_DEVICE_SYSTEM_VERSION(v) [DEVICE_SYSTEM_VERSION compare:v options:NSNumericSearch]
#define SYSTEM_VERSION_EQUAL_TO(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) != NSOrderedDescending)
.mm file
NSString* getOperatingSystemVerisonCode()
{
/*
[[NSProcessInfo processInfo] operatingSystemVersionString]
*/
NSDictionary *systemVersionDictionary =
[NSDictionary dictionaryWithContentsOfFile:
#"/System/Library/CoreServices/SystemVersion.plist"];
NSString *systemVersion =
[systemVersionDictionary objectForKey:#"ProductVersion"];
return systemVersion;
}
Linker Error:
Undefined symbols for architecture x86_64:
"_getOperatingSystemVerisonCode", referenced from:
-[Manager isFeatureAvailable] in Manager.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The problem is not caused by the macro definition.
The getOperatingSystemVerisonCode() function is defined in a ".mm" file and therefore
compiled as Objective-C++. In particular, the function name is mangled as a C++ function.
But when referenced from (Objective-)C sources, the unmangled name is expected.
You have two options to solve the problem:
Rename the ".mm" file to ".m", so that it is compiled as an Objective-C file.
In the header file where the function is declared, add the extern "C" declaration to enforce C linkage even in an (Objective-)C++ file:
#ifdef __cplusplus
extern "C" {
#endif
NSString* getOperatingSystemVerisonCode();
#ifdef __cplusplus
}
#endif
For more information about mixing C and C++, see for example
Combining C++ and C - how does #ifdef __cplusplus work?

Wrap calls to NSLog in Objective-C [duplicate]

This question already has answers here:
Setting a flag in compiler for NSLog not to show
(7 answers)
Closed 9 years ago.
I want to be able to wrap all calls to NSLog in my Class so I can have a single place to enable/disable logging.
I can't figure out how to accept variable numbers of arguments to my method and then hand them on to NSLog.
Examples, please.
for a logger I'd just go with a macro
#if DEBUG
#warning LOGGING ENABLED
#define DebugLog(fmt, ...) NSLog((#"%s " fmt), __PRETTY_FUNCTION__, ##__VA_ARGS__)
#else
#define DebugLog(...)
#endif
BUT
if you want to work with variable arguments:
declare your method as so it takes a variable number of arguments
+ (id)stringWithFormat:(NSString *)format, ...;
use the va_* C functions to interact with the variable arguments
va_start - Initializes a va_list
va_arg - Fetches the next argument out of the list.
va_end - Releases any memory by the list of vas
DEMO for the logging
#import <Foundation/Foundation.h>
#define DEBUG 1
#if DEBUG
#warning LOGGING ENABLED
#define DebugLog(fmt, ...) NSLog((#"%s " fmt), __PRETTY_FUNCTION__, ##__VA_ARGS__)
#else
#define DebugLog(...)
#endif
int main(int argc, char *argv[]) {
#autoreleasepool {
id v = #1;
DebugLog(#"bla: %#", v);
}
}
I use a handy set of Macros from Marcus Zarra:
#ifdef DEBUG
#define DLog(...) NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#define ALog(...) [[NSAssertionHandler currentHandler] handleFailureInFunction:[NSString stringWithCString:__PRETTY_FUNCTION__ encoding:NSUTF8StringEncoding] file:[NSString stringWithCString:__FILE__ encoding:NSUTF8StringEncoding] lineNumber:__LINE__ description:__VA_ARGS__]
#else
#define DLog(...) do { } while (0)
#ifndef NS_BLOCK_ASSERTIONS
#define NS_BLOCK_ASSERTIONS
#endif
#define ALog(...) NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#endif
#define ZAssert(condition, ...) do { if (!(condition)) { ALog(__VA_ARGS__); }} while(0)
This doesn't need any configuration as DEBUG and RELEASE are defined by Xcode as standard. This provides:
DLog() Only emits an NSLog in DEBUG
ALog() Throws an assertion with the message in DEBUG, and emits an NSLog in RELEASE
ZAssert() Throws an Assertion if the condition fails in DEBUG, and emits an NSLog if the condition fails in RELEASE.
And the logs are pretty printed - showing the class and method where the log is emitted.

Preprocessor macro and BOOL weirdness

Code below yields the output "yes defined", "no defined" and "yes". Why?
#define FOOBAR NO
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef YES
NSLog(#"yes defined");
#endif
#ifdef NO
NSLog(#"no defined");
#endif
#if FOOBAR == YES
NSLog(#"yes");
#else
NSLog(#"no");
#endif
// ...
}
YES and NO are not undefined, objc.h defines them as:
typedef signed char BOOL;
#define YES (BOOL)1
#define NO (BOOL)0
What is the value of NO? If it's undefined (like YES), they will both evaluate to 0.
This means your expression is essentially
#if 0 == 0
which is of course true, and thus causes the first call to be compiled.
UPDATE: Not sure how BOOL is defined, but casting to what might be a typedef:ed type is not a very good idea when dealing with the preprocessor. Remember that the the #if is evaluated by the preprocessor, not by the compiler. Read something like this for more information about expressions in the preprocessor. Especially:
The preprocessor does not know anything about types in the language.
All identifieres that the preprocessor doesn't know of are replaced with 0 for evaluation in #if directives. If you don't have defined YES and NO both are 0 (and thus equal).

Using constant to declare an array of item

Is it possible to use some thing like this in Objective-C:
#define number_of_items 10
and then using it as:
int arr[number_of_items];
Yes, assuming you mean Objective C. It's pretty much a superset of "proper" C so this is perfectly okay. It's also okay in both C and C++.
You can see that it works in the following transcript:
pax> cat qq.m
#import <objc/Object.h>
// First method.
#define number_of_items 10
int arr[number_of_items];
// Second method.
#define NUMBER_OF_ROWS 10
#interface test : Object{ int xyzzy[NUMBER_OF_ROWS]; }
#end;
pax> vi qq.m ; gcc -o qq.o -c qq.m -lobjc
pax> # no errors occurred
And, now that we've finally seen what you're actually using:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define NUMBER_OF_ROWS_ (IS_IPAD? 18: 18)
NUMBER_OF_ROWS_ is not a constant, since it depends on the return value of the function UI_USER_INTERFACE_IDIOM().
In other words, it cannot be calculated at compile time. That's why you're getting the error. You can see this by compiling the following code:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define NUMBER_OF_ROWS_ (IS_IPAD ? 18: 20)
int UI_USER_INTERFACE_IDIOM(void) {return 20;}
int UIUserInterfaceIdiomPad;
int main (void) {
int arr[NUMBER_OF_ROWS_];
return 0;
}
Under gcc --pedantic, you get:
qq.m: In function ‘main’:
qq.m:8: warning: ISO C90 forbids variable length array ‘arr’
You either need to use a dynamically adjustable collection like NSMutableArray or use an array of the maximum size desired and only use what you need of that.

How to print out the method name and line number and conditionally disable NSLog?

I'm doing a presentation on debugging in Xcode and would like to get more information on using NSLog efficiently.
In particular, I have two questions:
is there a way to easily NSLog the current method's name / line number?
is there a way to "disable" all NSLogs easily before compiling for release code?
Here are some useful macros around NSLog I use a lot:
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
# define DLog(...)
#endif
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
The DLog macro is used to only output when the DEBUG variable is set (-DDEBUG in the projects's C flags for the debug confirguration).
ALog will always output text (like the regular NSLog).
The output (e.g. ALog(#"Hello world") ) will look like this:
-[LibraryController awakeFromNib] [Line 364] Hello world
I've taken DLog and ALog from above, and added ULog which raises a UIAlertView message.
To summarize:
DLog will output like NSLog only when the DEBUG variable is set
ALog will always output like NSLog
ULog will show the UIAlertView only when the DEBUG variable is set
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...)
#endif
#define ALog(fmt, ...) NSLog((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#ifdef DEBUG
# define ULog(fmt, ...) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:#"%s\n [Line %d] ", __PRETTY_FUNCTION__, __LINE__] message:[NSString stringWithFormat:fmt, ##__VA_ARGS__] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil]; [alert show]; }
#else
# define ULog(...)
#endif
This is what it looks like:
+1 Diederik
NSLog(#"%s %d %s %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, __FUNCTION__);
Outputs file name, line number, and function name:
/proj/cocoa/cdcli/cdcli.m 121 managedObjectContext managedObjectContext
__FUNCTION__ in C++ shows mangled name __PRETTY_FUNCTION__ shows nice function name, in cocoa they look the same.
I'm not sure what is the proper way of disabling NSLog, I did:
#define NSLog
And no logging output showed up, however I don't know if this has any side effects.
Here one big collection of debug constants that we use. Enjoy.
// Uncomment the defitions to show additional info.
// #define DEBUG
// #define DEBUGWHERE_SHOWFULLINFO
// #define DEBUG_SHOWLINES
// #define DEBUG_SHOWFULLPATH
// #define DEBUG_SHOWSEPARATORS
// #define DEBUG_SHOWFULLINFO
// Definition of DEBUG functions. Only work if DEBUG is defined.
#ifdef DEBUG
#define debug_separator() NSLog( #"────────────────────────────────────────────────────────────────────────────" );
#ifdef DEBUG_SHOWSEPARATORS
#define debug_showSeparators() debug_separator();
#else
#define debug_showSeparators()
#endif
/// /// /// ////// /////
#ifdef DEBUG_SHOWFULLPATH
#define debug_whereFull() debug_showSeparators(); NSLog(#"Line:%d : %s : %s", __LINE__,__FILE__,__FUNCTION__); debug_showSeparators();
#else
#define debug_whereFull() debug_showSeparators(); NSLog(#"Line:%d : %s : %s", __LINE__,[ [ [ [NSString alloc] initWithBytes:__FILE__ length:strlen(__FILE__) encoding:NSUTF8StringEncoding] lastPathComponent] UTF8String ] ,__FUNCTION__); debug_showSeparators();
#endif
/// /// /// ////// /////
#define debugExt(args,...) debug_separator(); debug_whereFull(); NSLog( args, ##__VA_ARGS__); debug_separator();
/// /// /// ////// ///// Debug Print Macros
#ifdef DEBUG_SHOWFULLINFO
#define debug(args,...) debugExt(args, ##__VA_ARGS__);
#else
#ifdef DEBUG_SHOWLINES
#define debug(args,...) debug_showSeparators(); NSLog([ NSString stringWithFormat:#"Line:%d : %#", __LINE__, args ], ##__VA_ARGS__); debug_showSeparators();
#else
#define debug(args,...) debug_showSeparators(); NSLog(args, ##__VA_ARGS__); debug_showSeparators();
#endif
#endif
/// /// /// ////// ///// Debug Specific Types
#define debug_object( arg ) debug( #"Object: %#", arg );
#define debug_int( arg ) debug( #"integer: %i", arg );
#define debug_float( arg ) debug( #"float: %f", arg );
#define debug_rect( arg ) debug( #"CGRect ( %f, %f, %f, %f)", arg.origin.x, arg.origin.y, arg.size.width, arg.size.height );
#define debug_point( arg ) debug( #"CGPoint ( %f, %f )", arg.x, arg.y );
#define debug_bool( arg ) debug( #"Boolean: %#", ( arg == YES ? #"YES" : #"NO" ) );
/// /// /// ////// ///// Debug Where Macros
#ifdef DEBUGWHERE_SHOWFULLINFO
#define debug_where() debug_whereFull();
#else
#define debug_where() debug(#"%s",__FUNCTION__);
#endif
#define debug_where_separators() debug_separator(); debug_where(); debug_separator();
/// /// /// ////// /////
#else
#define debug(args,...)
#define debug_separator()
#define debug_where()
#define debug_where_separators()
#define debug_whereFull()
#define debugExt(args,...)
#define debug_object( arg )
#define debug_int( arg )
#define debug_rect( arg )
#define debug_bool( arg )
#define debug_point( arg )
#define debug_float( arg )
#endif
There are a new trick that no answer give. You can use printf instead NSLog. This will give you a clean log:
With NSLog you get things like this:
2011-11-03 13:43:55.632 myApp[3739:207] Hello Word
But with printf you get only:
Hello World
Use this code
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(...) {}
#endif
My answer to this question might help, looks like it's similar to the one Diederik cooked up. You may also want to replace the call to NSLog() with a static instance of your own custom logging class, that way you can add a priority flag for debug/warning/error messages, send messages to a file or database as well as the console, or pretty much whatever else you can think of.
#define DEBUG_MODE
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog( #"<%p %#:(%d)> %#", self,
[[NSString stringWithUTF8String:__FILE__] lastPathComponent],
__LINE__,
[NSString stringWithFormat:(s),
##__VA_ARGS__] )
#else
#define DebugLog( s, ... )
#endif
Disabling all NSLogs, for somebody allergic to MACROS, here is something that you can compile too:
void SJLog(NSString *format,...)
{
if(LOG)
{
va_list args;
va_start(args,format);
NSLogv(format, args);
va_end(args);
}
}
And, use it almost like NSLog:
SJLog(#"bye bye NSLogs !");
From this blog: https://whackylabs.com/logging/ios/2011/01/19/ios-moving-in-and-out-of-nslogs/
To complement the answers above, it can be quite useful to use a replacement for NSLog in certain situations, especially when debugging. For example, getting rid of all the date and process name/id information on each line can make output more readable and faster to boot.
The following link provides quite a bit of useful ammo for making simple logging much nicer.
http://cocoaheads.byu.edu/wiki/a-different-nslog
It's easy to change your existing NSLogs to display line number and class from which they are called. Add one line of code to your prefix file:
#define NSLog(__FORMAT__, ...) NSLog((#"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
It is simple,for Example
-(void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(#"%s", __PRETTY_FUNCTION__);
}
Output:
-[AppDelegate applicationWillEnterForeground:]
building on top of above answers, here is what I plagiarized and came up with. Also added memory logging.
#import <mach/mach.h>
#ifdef DEBUG
# define DebugLog(fmt, ...) NSLog((#"%s(%d) " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DebugLog(...)
#endif
#define AlwaysLog(fmt, ...) NSLog((#"%s(%d) " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#ifdef DEBUG
# define AlertLog(fmt, ...) { \
UIAlertView *alert = [[UIAlertView alloc] \
initWithTitle : [NSString stringWithFormat:#"%s(Line: %d) ", __PRETTY_FUNCTION__, __LINE__]\
message : [NSString stringWithFormat : fmt, ##__VA_ARGS__]\
delegate : nil\
cancelButtonTitle : #"Ok"\
otherButtonTitles : nil];\
[alert show];\
}
#else
# define AlertLog(...)
#endif
#ifdef DEBUG
# define DPFLog NSLog(#"%s(%d)", __PRETTY_FUNCTION__, __LINE__);//Debug Pretty Function Log
#else
# define DPFLog
#endif
#ifdef DEBUG
# define MemoryLog {\
struct task_basic_info info;\
mach_msg_type_number_t size = sizeof(info);\
kern_return_t e = task_info(mach_task_self(),\
TASK_BASIC_INFO,\
(task_info_t)&info,\
&size);\
if(KERN_SUCCESS == e) {\
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; \
[formatter setNumberStyle:NSNumberFormatterDecimalStyle]; \
DebugLog(#"%# bytes", [formatter stringFromNumber:[NSNumber numberWithInteger:info.resident_size]]);\
} else {\
DebugLog(#"Error with task_info(): %s", mach_error_string(e));\
}\
}
#else
# define MemoryLog
#endif
New addition to DLog. Instead of totally removing debug from released application, only disable it. When user has problems, which would require debugging, just tell how to enable debug in released application and request log data via email.
Short version: create global variable (yes, lazy and simple solution) and modify DLog like this:
BOOL myDebugEnabled = FALSE;
#define DLog(fmt, ...) if (myDebugEnabled) NSLog((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
Longer answer at Jomnius iLessons iLearned: How to Do Dynamic Debug Logging in Released Application
For some time I've been using a site of macros adopted from several above. Mine focus on logging in the Console, with the emphasis on controlled & filtered verbosity; if you don't mind a lot of log lines but want to easily switch batches of them on & off, then you might find this useful.
First, I optionally replace NSLog with printf as described by #Rodrigo above
#define NSLOG_DROPCHAFF//comment out to get usual date/time ,etc:2011-11-03 13:43:55.632 myApp[3739:207] Hello Word
#ifdef NSLOG_DROPCHAFF
#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#endif
Next, I switch logging on or off.
#ifdef DEBUG
#define LOG_CATEGORY_DETAIL// comment out to turn all conditional logging off while keeping other DEBUG features
#endif
In the main block, define various categories corresponding to modules in your app. Also define a logging level above which logging calls won't be called. Then define various flavours of NSLog output
#ifdef LOG_CATEGORY_DETAIL
//define the categories using bitwise leftshift operators
#define kLogGCD (1<<0)
#define kLogCoreCreate (1<<1)
#define kLogModel (1<<2)
#define kLogVC (1<<3)
#define kLogFile (1<<4)
//etc
//add the categories that should be logged...
#define kLOGIFcategory kLogModel+kLogVC+kLogCoreCreate
//...and the maximum detailLevel to report (use -1 to override the category switch)
#define kLOGIFdetailLTEQ 4
// output looks like this:"-[AppDelegate myMethod] log string..."
# define myLog(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((#"%s " format), __PRETTY_FUNCTION__, ##__VA_ARGS__);}
// output also shows line number:"-[AppDelegate myMethod][l17] log string..."
# define myLogLine(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((#"%s[l%i] " format), __PRETTY_FUNCTION__,__LINE__ ,##__VA_ARGS__);}
// output very simple:" log string..."
# define myLogSimple(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((#"" format), ##__VA_ARGS__);}
//as myLog but only shows method name: "myMethod: log string..."
// (Doesn't work in C-functions)
# define myLog_cmd(category,detailLevel,format,...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((#"%#: " format), NSStringFromSelector(_cmd), ##__VA_ARGS__);}
//as myLogLine but only shows method name: "myMethod>l17: log string..."
# define myLog_cmdLine(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((#"%#>l%i: " format), NSStringFromSelector(_cmd),__LINE__ , ##__VA_ARGS__);}
//or define your own...
// # define myLogEAGLcontext(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((#"%s>l%i (ctx:%#)" format), __PRETTY_FUNCTION__,__LINE__ ,[EAGLContext currentContext], ##__VA_ARGS__);}
#else
# define myLog_cmd(...)
# define myLog_cmdLine(...)
# define myLog(...)
# define myLogLine(...)
# define myLogSimple(...)
//# define myLogEAGLcontext(...)
#endif
Thus, with current settings for kLOGIFcategory and kLOGIFdetailLTEQ, a call like
myLogLine(kLogVC, 2, #"%#",self);
will print but this won't
myLogLine(kLogGCD, 2, #"%#",self);//GCD not being printed
nor will
myLogLine(kLogGCD, 12, #"%#",self);//level too high
If you want to override the settings for an individual log call, use a negative level:
myLogLine(kLogGCD, -2, #"%#",self);//now printed even tho' GCD category not active.
I find the few extra characters of typing each line are worth as I can then
Switch an entire category of comment on or off (e.g. only report those calls marked Model)
report on fine detail with higher level numbers or just the most important calls marked with lower numbers
I'm sure many will find this a bit of an overkill, but just in case someone finds it suits their purposes..