NSLog the method name with Objective-C in iPhone

61,016

Solution 1

print(__FUNCTION__) // Swift
NSLog(@"%@", NSStringFromSelector(_cmd)); // Objective-C

Swift 3 and above

print(#function)

Solution 2

To technically answer your question, you want:

NSLog(@"<%@:%@:%d>", NSStringFromClass([self class]), NSStringFromSelector(_cmd), __LINE__);

Or you could also do:

NSLog(@"%s", __PRETTY_FUNCTION__);

Solution 3

tl;dr

NSLog( @"ERROR %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

Details

Apple has a Technical Q&A page: QA1669 - How can I add context information - such as the current method or line number - to my logging statements?

To assist with logging:

  • The C preprocessor provides a few macros.
  • Objective-C provides expressions (methods).
    • Pass the implicit argument for the current method's selector: _cmd

As other answers indicated, to merely get the current method's name, call:

NSStringFromSelector(_cmd)

To get the current method name and current line number, use these two macros __func__ and __LINE__ as seen here:

NSLog(@"%s:%d someObject=%@", __func__, __LINE__, someObject);

Another example… Snippets of code I keep in Xcode's Code Snippet Library:

NSLog( @"ERROR %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

…and TRACE instead of ERROR…

NSLog( @"TRACE %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

…and a longer one using a soft-coded description passing a value ([rows count])…

NSLog( @"TRACE %@ METHOD %s:%d.", [NSString stringWithFormat:@"'Table of Contents.txt' file's count of Linefeed-delimited rows: %u.", [rows count]] , __func__, __LINE__ );

Preprocessor macros for logging

Note the use of a pair of underscore characters around both sides of the macro.

| Macro                | Format   | Description
  __func__               %s         Current function signature
  __LINE__               %d         Current line number
  __FILE__               %s         Full path to source file
  __PRETTY_FUNCTION__    %s         Like __func__, but includes verbose
                                    type information in C++ code. 

Expressions for logging

| Expression                       | Format   | Description
  NSStringFromSelector(_cmd)         %@         Name of the current selector
  NSStringFromClass([self class])    %@         Current object's class name
  [[NSString                         %@         Source code file name
    stringWithUTF8String:__FILE__]   
    lastPathComponent] 
  [NSThread callStackSymbols]        %@         NSArray of stack trace

Logging Frameworks

Some logging frameworks may help with getting current method or line number as well. I'm not sure, as I've used a great logging framework in Java (SLF4J + LogBack) but not Cocoa.

See this question for links to various Cocoa logging frameworks.

Name of Selector

If you have a Selector variable (a SEL), you can print its method name ("message") in either of two ways as described by this Codec blog post:

  • Using Objective-C call to NSStringFromSelector:
    NSLog(@"%@", NSStringFromSelector(selector) );
  • Using straight C:
    NSLog(@"%s", selector );

This information drawn from the linked Apple doc page as of 2013-07-19. That page had been last updated 2011-10-04.

Solution 4

NSLog(@"%@", NSStringFromSelector(_cmd)); // Objective-C
print(__FUNCTION__) // Swift
Share:
61,016

Related videos on Youtube

vodkhang
Author by

vodkhang

I am interested in quite a range of things from hard core like database system, intelligent to mobile and Human Usability @vodkhang My blog

Updated on December 10, 2020

Comments

  • vodkhang
    vodkhang over 3 years

    Currently, we are defining ourselves an extended log mechanism to print out the class name and the source line number of the log.

    #define NCLog(s, ...) NSLog(@"<%@:%d> %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], \
        __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__])
    

    For example, when I call NCLog(@"Hello world"); The output will be:

    <ApplicationDelegate:10>Hello world
    

    Now I also want to log out the method name like:

    <ApplicationDelegate:applicationDidFinishLaunching:10>Hello world
    

    So, this would make our debugging become easier when we can know which method is getting called. I know that we also have Xcode debugger but sometimes, I also want to do debugging by logging out.

    • Jacob Relkin
      Jacob Relkin about 14 years
      In my last iPhone project, I actually did this manually. Would love to see the answer to this.
    • erkanyildiz
      erkanyildiz about 10 years
  • Georg Fritzsche
    Georg Fritzsche about 14 years
    With __FUNCTION__ and its pretty equivalent also being available in C-functions.
  • Nick Forge
    Nick Forge about 14 years
    You really should use NSLog(@"%@", NSStringFromSelector(_cmd)), if you're going to use _cmd, since AFAIK Apple declares _cmd as type SEL, not a C-string. Just because it happens to be implemented as a C-string (as of the current versions of Mac OS X and the iPhone OS) doesn't mean you should use it in that way, since Apple could change it in an OS update.
  • drawnonward
    drawnonward about 14 years
    Yes, NSStringFromSelector is the more correct answer. I never use _cmd as c string for anything but debug code.
  • Nicolas Miari
    Nicolas Miari about 12 years
    Wow, the compiler complaints about pointer incompatibility, but it works... So _cmd (type: SEL) really is a char* !?
  • Jack Lawrence
    Jack Lawrence over 11 years
    Method calls like [self doSomething:arg1 somethingElse:arg2] get converted into the C function call objc_msgSend(self, "doSomething:somethingElse:, arg1, arg2);. The second parameter of objc_msgSend() takes a char*. Remember that because the Objective-C runtime is dynamic, it's actually using a lookup table to figure out which method on which class to call so a char* is convenient since methods are represented as strings in the lookup table.
  • Ethan Reesor
    Ethan Reesor over 10 years
    For C, use sel_getName(SEL) since SEL is an opaque type and might not always be a char *
  • OrangeDog
    OrangeDog over 10 years
    N.B. __FUNCTION__ also includes the class name
  • FreeNickname
    FreeNickname about 9 years
    For anyone who comes across this answer in the future: it is equivalent to the accepted answer, but the accepted answer was different, when this one was posted (the accepted answer was edited in 2014). I was about to down vote, but after a small investigation up voted instead :)
  • Jake Lin
    Jake Lin about 8 years
    For Swift 2.2 should use print("\(#function)")
  • Ravi
    Ravi about 6 years
    is there any difference using NSLog(@"%s",_func_); OR NSLog(@"%s", _PRETTY_FUNCTION_) ???