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

Swift 3以降

print(#function)

120
使用NSLog(@"%@", NSStringFromSelector(_cmd))する場合_cmdは、AFAIK Apple がC文字列ではなく_cmdtypeとして宣言するため、実際にはを使用する必要がありSELます。それがたまたまC文字列として実装されているからといって(現在のバージョンのMac OS XおよびiPhone OSの時点で)、AppleがOSアップデートで変更できるため、そのように使用する必要があるわけではありません。
Nick Forge

5
はい、NSStringFromSelectorの方が正解です。_cmdをデバッグコード以外の文字列として使用することはありません。
描画

コンパイラーはポインターの非互換性について不平を言っていますが、動作します... _cmd(タイプ:SEL)は本当に char *です!?
Nicolas Miari

3
[self doSomething:arg1 somethingElse:arg2]getのようなメソッド呼び出しは、C関数呼び出しに変換されますobjc_msgSend(self, "doSomething:somethingElse:, arg1, arg2);。の2番目のパラメータはをobjc_msgSend()受け取りますchar*。Objective-Cランタイムは動的であるため、実際にはルックアップテーブルを使用して、どのクラスのどのメソッドを呼び出すかを判断しているため、メソッドはルックアップテーブルで文字列として表されるため、char *が便利です。
Jack Lawrence

1
Swift 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 2014年

1
NSLog(@ "%s"、_func_)を使用して違いはありますかまたはNSLog(@ "%s"、_PRETTY_FUNCTION_)???
ラビ

83

tl; dr

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

細部

Appleには技術的なQ&Aページがあります:QA1669-現在のメソッドや行番号などのコンテキスト情報をロギングステートメントに追加するにはどうすればよいですか?

ロギングを支援するには:

  • Cプリプロセッサはいくつかのマクロを提供します
  • Objective-Cは(メソッド)を提供します。
    • 現在のメソッドのセレクターに暗黙の引数を渡します_cmd

他の答えが示すように、単に現在のメソッドの名前を取得するには、次を呼び出します。

NSStringFromSelector(_cmd)

現在のメソッド名現在の行番号を取得するには、次の2つのマクロ__func__を使用し__LINE__ます。

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

別の例... Xcodeのコードスニペットライブラリに保持しているコードのスニペット:

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

…そしてエラーの代わりにトレース…

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ロギングフレームワークへのリンクについては、この質問を参照してください。

セレクターの名前

セレクター変数(SEL)がある場合、このコーデック ブログの投稿で説明されているように、2つの方法のいずれかでそのメソッド名(「メッセージ」)を出力できます。

  • NSStringFromSelectorへのObjective-C呼び出しの使用:
    NSLog(@"%@", NSStringFromSelector(selector) );
  • ストレートCを使用:
    NSLog(@"%s", selector );

この情報は、2013年7月19日現在のリンクされたAppleのドキュメントページから取得されました。そのページは最後に更新されました2011-10-04。


1
Cの場合sel_getName(SEL)、SELは不透明なタイプであり、常にaであるとは限らないので使用しますchar *
Ethan Reesor

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

4
将来この回答に遭遇した人にとって:これは承認された回答と同じですが、投稿されたときに承認された回答は異なりました(承認された回答は2014年に編集されました)。私は反対票を投じようとしていましたが、小さな調査の後、代わりに反対票を投じました:)
FreeNickname 2015

0

実際には次のように簡単です。

printf(_cmd);

なんらかの理由で、iOSでは_cmdをリテラル文字として渡すことができ、コンパイルの警告すらありません。知るか


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.