私はこのサイトでこれを何度か言われましたが、私はこれが本当にそうであることを確認したかったのです。
私はコード全体にNSLog関数呼び出しを振りかけることができると期待していました、そしてXcode / gccは私のリリース/配布ビルドをビルドするときにそれらの呼び出しを自動的に取り除くでしょう。
これは使用しないでください。もしそうなら、経験豊富なObjective-Cプログラマの間で最も一般的な代替手段は何ですか?
私はこのサイトでこれを何度か言われましたが、私はこれが本当にそうであることを確認したかったのです。
私はコード全体にNSLog関数呼び出しを振りかけることができると期待していました、そしてXcode / gccは私のリリース/配布ビルドをビルドするときにそれらの呼び出しを自動的に取り除くでしょう。
これは使用しないでください。もしそうなら、経験豊富なObjective-Cプログラマの間で最も一般的な代替手段は何ですか?
回答:
プリプロセッサマクロは確かにデバッグに最適です。NSLog()には何の問題もありませんが、より優れた機能を備えた独自のロギング関数を定義するのは簡単です。これが私が使用するものです。ログステートメントを追跡しやすくするために、ファイル名と行番号が含まれています。
#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
このステートメント全体を、独自のファイルではなく接頭辞ヘッダーに入れる方が簡単だと思いました。必要に応じて、DebugLogを通常のObjective-Cオブジェクトと相互作用させることで、より複雑なログシステムを構築できます。たとえば、独自のログファイル(またはデータベース)に書き込み、実行時に設定できる 'priority'引数を含むロギングクラスを使用できるため、デバッグバージョンはリリースバージョンに表示されませんが、エラーメッセージは(これを行った場合、DebugLog()、WarningLog()などを作成できます)。
ああ、覚えておい#define DEBUG_MODE
てください。アプリケーションのさまざまな場所で再利用できます。たとえば、私のアプリケーションでは、それを使用してライセンスキーチェックを無効にし、特定の日付より前の場合にのみアプリケーションを実行できるようにします。これにより、期間限定の完全に機能するベータ版コピーを、最小限の労力で配布できます。
NSLog呼び出しは本番コードに残すことができますが、本当に例外的な場合、またはシステムログに記録されることが望ましい情報の場合にのみ存在する必要があります。
システムログを散らかすアプリケーションは煩わしく、専門家ではないように出くわします。
マークシャルボノーの回答にはコメントできないので、回答として投稿します。
マクロをプリコンパイル済みヘッダーに追加するだけでなく、ターゲットビルド構成を使用して、の定義(または定義の欠如)を制御できますDEBUG_MODE
。
「デバッグ」を選択DEBUG_MODE
すると、アクティブ構成が定義され、マクロが完全NSLog
な定義に展開されます。
「リリース」のアクティブ構成をも定義は行われず、リリースビルドからギングは省略されDEBUG_MODE
ますNSLog
。
手順:
GCC_PREPROCESSOR_DEFINITIONS
)をDEBUG_MODE=1
DEBUG_MODE
が設定されていませんGCC_PREPROCESSOR_DEFINITIONS
定義で '='文字を省略すると、プリプロセッサからエラーが発生します
また、このコメント(下に表示)をマクロ定義の上に貼り付けて、DEBUG_MACRO
定義がどこから来たかを通知します;)
// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
// = Debug: DEBUG_MODE=1
DEBUG_MODE
そしてDEBUG_MACRO
、型破りです。DEBUG_MACRO
アップルのサイト(opensource.apple.com/source/gm4/gm4-15/src/m4.h?txt)で参照しているのは1つだけです。おそらくより標準的でDEBUG
、NDEBUG
より良い選択でしょうか?NDEBUG
Posixによって指定されています。while DEBUG
は慣例により使用されます。
EDIT:この方法は、によって投稿マルクCharbonneau、およびによって私の注意に持って来ら笙、はるかに優れたこの1を超えています。
デバッグモードが無効になっているときにログを無効にするために空の関数を使用することを提案した私の回答の部分を削除しました。自動プリプロセッサマクロの設定を扱う部分はまだ関連があるため、そのまま残します。Marc Charbonneauの答えに合うように、プリプロセッサマクロの名前も編集しました。
Xcodeで自動(および期待される)動作を実現するには:
プロジェクト設定で、[ビルド]タブに移動し、[デバッグ]構成を選択します。「プリプロセッサマクロ」セクションを見つけて、次の名前のマクロを追加します。DEBUG_MODE
ます。
...
編集:マクロでログを有効または無効にする適切な方法については、Marc Charbonneauの回答を参照してくださいDEBUG_MODE
。
単純な真実は、NSLogは非常に遅いということです。
しかし、なぜ?その質問に答えるために、NSLogが何をするか、そしてそれがどのようにそれを行うかを調べましょう。
NSLogは正確に何をしますか?
NSLogは2つのことを行います。
ログメッセージをApple System Logging(asl)機能に書き込みます。これにより、ログメッセージがConsole.appに表示されます。また、アプリケーションのstderrストリームがターミナルに送信されるかどうかも確認します(アプリケーションがXcode経由で実行されている場合など)。その場合、ログメッセージをstderrに書き込みます(Xcodeコンソールに表示されるようにするため)。
STDERRへの書き込みは難しくありません。これは、fprintfおよびstderrファイル記述子リファレンスを使用して実行できます。しかし、ASLはどうですか?
ASLについて私が見つけた最高のドキュメントは、Peter Hoseyからの10部のブログ投稿です。 リンク
詳細には触れませんが、ハイライト(パフォーマンスに関する)は次のとおりです。
ログメッセージをASL機能に送信するには、基本的にASLデーモンへのクライアント接続を開いてメッセージを送信します。BUT-各スレッドは個別のクライアント接続を使用する必要があります。そのため、スレッドセーフになるために、NSLogが呼び出されるたびに、NSLは新しいaslクライアント接続を開き、メッセージを送信して、接続を閉じます。
他の回答で述べたように、#defineを使用して、コンパイル時にNSLogを使用するかどうかを変更できます。
ただし、より柔軟な方法は、Cocoa Lumberjackのようなロギングライブラリを使用することです。、実行時に何かがログに記録されるかどうかを変更ことです。
コードでNSLogをDDLogVerboseやDDLogErrorなどで置き換え、マクロ定義などの#importを追加して、多くの場合applicationDidFinishLaunchingメソッドでロガーを設定します。
NSLogと同じ効果を持つために、構成コードは
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
セキュリティの観点からは、何がログに記録されているかによって異なります。もしNSLog
、機密情報を書き込んでいる(または他のロガー)、そして本番コードでロガーを削除する必要があります。
監査の観点から、監査人は、 NSLog
機密情報がログに記録されないことを確認するためにのを確認する必要はありません。彼/彼女はロガーを取り除くようにあなたに単に言うでしょう。
私は両方のグループと協力しています。私たちはコードを監査し、コーディングガイドなどを書きます。私たちのガイドでは、プロダクションコードではロギングを無効にする必要があります。したがって、内部チームはそれを試さないことを知っています;)
また、機密情報が誤って漏洩することに伴うリスクを受け入れたくないため、本番環境にログインする外部アプリも拒否します。開発者が何を言っても気にしません。調査するだけの価値はありません。
そして、開発者ではなく「機密」を定義することを忘れないでください;)
また、大量のロギングを実行するアプリを、内破可能なアプリとして認識しています。多くのロギングが実行/必要とされる理由があり、通常は安定性がありません。そのすぐ上に、ハングしたサービスを再開する「ウォッチドッグ」スレッドがあります。
セキュリティアーキテクチャ(SecArch)のレビューを一度も行ったことがない場合、これらは私たちが検討しているものです。
リリースコードのprintfやNSLogを不必要に冗長にするべきではありません。アプリに何か問題が発生した場合にのみ、printfまたはNSLogを実行してみてください。IEは回復不可能なエラーです。
ロギングにはTestFlightを使用することを強くお勧めします(無料)。それらのメソッドはNSLogをオーバーライドし(マクロを使用)、NSLogへの既存のすべての呼び出しに対して、サーバー、Appleシステムログ、およびSTDERRログへのロギングをオン/オフにすることができます。これの良い点は、ユーザーのシステムログにログが表示されなくても、テスターにデプロイされたアプリとApp Storeにデプロイされたアプリのログメッセージを引き続き確認できることです。両方の世界のベスト。