ChatGPT解决这个技术问题 Extra ChatGPT

NSLog iPhone中Objective-C的方法名

目前,我们正在为自己定义一个扩展日志机制来打印日志的类名和源行号。

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

例如,当我调用 NCLog(@"Hello world");输出将是:

<ApplicationDelegate:10>Hello world

现在我还想注销方法名称,例如:

<ApplicationDelegate:applicationDidFinishLaunching:10>Hello world

因此,当我们知道调用了哪个方法时,这将使我们的调试变得更容易。我知道我们也有 Xcode 调试器,但有时我也想通过注销来进行调试。

在我上一个 iPhone 项目中,我实际上是手动完成的。很想看到这个问题的答案。

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

斯威夫特 3 及以上

print(#function)

如果您要使用 _cmd,您真的应该使用 NSLog(@"%@", NSStringFromSelector(_cmd)),因为 AFAIK Apple 将 _cmd 声明为类型 SEL,而不是 C 字符串。仅仅因为它恰好被实现为 C 字符串(从 Mac OS X 和 iPhone OS 的当前版本开始)并不意味着您应该以这种方式使用它,因为 Apple 可以在 OS 更新中更改它。
是的, NSStringFromSelector 是更正确的答案。除了调试代码,我从不使用 _cmd 作为 c 字符串。
哇,编译器抱怨指针不兼容,但它可以工作......所以 _cmd (type: SEL) 真的是 char* !?
[self doSomething:arg1 somethingElse:arg2] 这样的方法调用被转换为 C 函数调用 objc_msgSend(self, "doSomething:somethingElse:, arg1, arg2);objc_msgSend() 的第二个参数采用 char*。请记住,由于 Objective-C 运行时是动态的,它实际上使用查找表来确定要调用哪个类的哪个方法,因此 char* 很方便,因为方法在查找表中表示为字符串。
对于 Swift 2.2 应该使用 print("\(#function)")
D
Dave DeLong

要从技术上回答您的问题,您需要:

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

或者你也可以这样做:

NSLog(@"%s", __PRETTY_FUNCTION__);

__FUNCTION__ 及其相当等价的内容也可用于 C 函数。
注意 __FUNCTION__ 还包括类名
使用 NSLog(@"%s",_func_); 有什么区别吗?或 NSLog(@"%s", _PRETTY_FUNCTION_) ???
C
Community

tl;博士

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

细节

Apple 有一个技术问答页面:QA1669 - How can I add context information - such as the current method or line number - to my logging statements?

协助记录:

C 预处理器提供了一些宏。

Objective-C 提供表达式(方法)。为当前方法的选择器传递隐式参数:_cmd

为当前方法的选择器传递隐式参数:_cmd

正如其他答案所示,仅获取当前方法的名称,请调用:

NSStringFromSelector(_cmd)

要获取当前方法名称当前行号,请使用这两个宏 __func____LINE__,如下所示:

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

另一个例子……我保存在 Xcode 的代码片段库中的代码片段:

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

…和 TRACE 而不是 ERROR…

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

…还有一个较长的使用软编码描述传递值 ([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__ );

用于记录的预处理器宏

请注意在宏的两侧使用一对下划线字符。

| 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.

日志记录表达式

| 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

日志框架

一些日志框架也可能有助于获取当前方法或行号。我不确定,因为我在 Java (SLF4J + LogBack) 中使用了一个很棒的日志框架,但不是 Cocoa。

有关各种 Cocoa 日志框架的链接,请参阅 this question

选择器名称

如果您有一个 Selector 变量(一个 SEL),您可以按此 Codec blog post 所述的两种方式之一打印其方法名称(“消息”):

使用 Objective-C 调用 NSStringFromSelector: NSLog(@"%@", NSStringFromSelector(selector) );

使用直接 C: NSLog(@"%s", selector );

截至 2013 年 7 月 19 日,此信息来自链接的 Apple 文档页面。该页面上次更新时间为 2011 年 10 月 4 日。


对于 C,请使用 sel_getName(SEL),因为 SEL 是一种不透明类型,可能并不总是 char *
H
Huynh Inc
NSLog(@"%@", NSStringFromSelector(_cmd)); // Objective-C
print(__FUNCTION__) // Swift

对于将来遇到此答案的任何人:它等同于已接受的答案,但在发布此答案时,已接受的答案有所不同(已在 2014 年编辑了已接受的答案)。我正要投反对票,但经过小型调查后投了赞成票:)
A
Albert Renshaw

它实际上很简单:

printf(_cmd);

出于某种原因,iOS 允许 _cmd 作为文字字符传递,甚至没有编译警告。谁知道


g
garg

在 Swift 4 中:

功能测试(){

print(#function)

}

test() //打印值“test()”