iPhone에서 Objective-C로 메소드 이름 NSLog


153

현재, 우리는 클래스 이름과 로그의 소스 라인 번호를 출력하는 확장 로그 메커니즘을 정의하고 있습니다.

#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프로젝트에서 실제로 수동으로 수행했습니다. 이것에 대한 답변을보고 싶습니다.
Jacob Relkin

답변:


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

스위프트 3 이상

print(#function)

120
AFAIK Apple은 C 문자열이 아닌 type으로 선언하므로을 NSLog(@"%@", NSStringFromSelector(_cmd))사용하려는 경우 실제로 사용해야 합니다. C- 문자열 (현재 Mac OS X 및 iPhone OS 버전)로 구현되었다고해서 Apple이 OS 업데이트에서 변경할 수 있기 때문에 그런 식으로 사용해야한다는 의미는 아닙니다. _cmd_cmdSEL
Nick Forge

5
예, NSStringFromSelector가 더 정답입니다. 디버그 코드 외에는 _cmd를 c 문자열로 사용하지 않습니다.
10:17에 drawnonward

와우, 컴파일러는 포인터 비 호환성에 대해 불평하지만 작동합니다 ... _cmd (유형 : SEL)는 실제로 char * !?
Nicolas Miari 2016 년

3
메소드 호출 [self doSomething:arg1 somethingElse:arg2]은 C 함수 호출로 변환됩니다 objc_msgSend(self, "doSomething:somethingElse:, arg1, arg2);. 의 두 번째 매개 변수는 objc_msgSend()을 사용합니다 char*. Objective-C 런타임은 동적이기 때문에 실제로는 조회 테이블을 사용하여 어떤 클래스를 호출 할 메소드를 찾아 내므로 char *가 편리하므로 메소드는 조회 테이블에서 문자열로 표시되므로 편리합니다.
잭 로렌스

1
스위프트 2.2의 경우print("\(#function)")
Jake Lin

161

기술적으로 질문에 대답하려면 다음을 원합니다.

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

또는 다음을 수행 할 수도 있습니다.

NSLog(@"%s", __PRETTY_FUNCTION__);

2
__FUNCTION__그 꽤 상당 또한 C-기능에서 사용할 수있는.
Georg Fritzsche

NB __FUNCTION__는 또한 클래스 이름을 포함합니다
OrangeDog

1
NSLog (@ "% s", _func_ )를 사용하여 차이점이 있습니까 ? 또는 NSLog (@ "% s", _PRETTY_FUNCTION_ ) ???
Ravi

83

tl; dr

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

세부

Apple은 기술 Q & A 페이지를 보유하고 있습니다 . QA1669-현재 방법 또는 라인 번호와 같은 컨텍스트 정보를 로깅 내역에 어떻게 추가 할 수 있습니까?

로깅을 지원하려면 다음을 수행하십시오.

  • C 전처리 기는 몇 가지 매크로를 제공 합니다 .
  • Objective-C는 표현식 (방법)을 제공합니다 .
    • 패스 암시 인수 현재 방법의 선택를 들어 :_cmd

다른 답변에서 알 수 있듯이 현재 메소드의 이름을 얻으려면 다음을 호출하십시오.

NSStringFromSelector(_cmd)

현재 메소드 이름 얻으려면 하고 , 현재의 행 번호를 두 매크로를 사용 __func__하고 __LINE__여기에서 볼 수 있듯이 :

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

또 다른 예 ... Xcode의 코드 스 니펫 라이브러리에 보관하는 코드 스 니펫 :

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

… 오류 대신 TRACE…

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__ );

로깅을위한 전 처리기 매크로

매크로의 양쪽에 한 쌍의 밑줄 문자를 사용하십시오.

| 매크로 | 형식 | 기술
  __func__ % s 현재 함수 서명
  __LINE__ % d 현재 줄 번호
  __FILE__ % s 소스 파일의 전체 경로
  __PRETTY_FUNCTION__ % s __func__와 유사하지만 자세한 정보 포함
                                    C ++ 코드의 유형 정보. 

로깅 표현식

| 표현 | 형식 | 기술
  NSStringFromSelector (_cmd) % @ 현재 선택기의 이름
  NSStringFromClass ([self class]) % @ 현재 객체의 클래스 이름
  [[NSString % @ 소스 코드 파일 이름
    stringWithUTF8String : __ FILE__]   
    lastPathComponent] 
  [NSThread callStackSymbols] % @ 스택 추적의 NSArray

로깅 프레임 워크

일부 로깅 프레임 워크는 현재 메소드 또는 행 번호를 얻는 데 도움이 될 수 있습니다. Java ( SLF4J + LogBack ) 에서 훌륭한 로깅 프레임 워크를 사용 했지만 Cocoa 는 사용하지 않았으므로 확실 하지 않습니다.

다양한 Cocoa 로깅 프레임 워크에 대한 링크는 이 질문 을 참조하십시오 .

선택기 이름

Selector 변수 ( SEL )가있는 경우이 코덱 블로그 게시물에 설명 된대로 두 가지 방법 중 하나로 메소드 이름 ( "message")을 인쇄 할 수 있습니다 .

  • NSStringFromSelector에 대한 Objective-C 호출 사용 :
    NSLog(@"%@", NSStringFromSelector(selector) );
  • 직선 C 사용 :
    NSLog(@"%s", selector );

이 정보는 2013-07-19 현재 연결된 Apple 문서 페이지에서 가져 왔습니다. 이 페이지는 2011-10-04에 마지막으로 업데이트되었습니다.


1
C의 경우 sel_getName(SEL)SEL은 불투명 한 유형이므로 항상 사용할 수있는 것은 아닙니다.char *
Ethan Reesor

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

4
미래 에이 답변을 보게되는 사람은 받아 들일 수있는 답변과 동일하지만이 답변을 게시했을 때 수락 된 답변이 다릅니다 (허용 된 답변은 2014 년에 편집되었습니다). 나는 투표를 중단하려고했지만, 약간의 조사 후에 투표가 대신 :)
FreeNickname

0

실제로 다음과 같이 간단합니다.

printf(_cmd);

어떤 이유로 iOS는 컴파일 경고조차하지 않고 _cmd를 리터럴 문자로 전달할 수 있습니다. 누가 알아


0

스위프트 4에서 :

기능 테스트 () {

print(#function)

}

test () // 값 "test ()"를 출력

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.