web-dev-qa-db-ja.com

アプリケーションをリリースする前にNSLogを無効にする必要がありますか?

IPhone用アプリをリリースするときに、NSLog();を無効にするとパフォーマンスが向上しますか?

115
RAGOpoR

それを行う1つの方法は、ビルド設定に移動し、デバッグ構成で「プリプロセッサマクロ」値に次のような値を追加することです。

DEBUG_MODE=1

ベータ版またはリリース版ではなく、デバッグ構成に対してのみこれを行うようにしてください。次に、共通のヘッダーファイルで次のようなことができます。

#ifdef DEBUG_MODE
#define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DLog( s, ... ) 
#endif

これで、NSLogの代わりにDLogをどこでも使用できます。テストとデバッグを行うと、デバッグメッセージが表示されます。ベータまたは最終リリースをリリースする準備ができたら、これらのDLog行はすべて自動的に空になり、何も出力されません。この方法では、変数の手動設定やNSLogsのコメントは必要ありません。ビルドターゲットを選択することで処理されます。

125
Ramin

Xcode 5およびiOS 7の更新

注:Xcode 7/Swift 2.1削除するソリューションprint()リリースビルドのステートメント、私の答えを見つけてください ここ

はい、コードを遅くするだけで、リリースバージョンでは役に立たないため、リリースコードのNSLogステートメントを削除する必要があります。幸いなことに、Xcode 5(iOS 7)では、リリースビルドですべてのNSLogステートメントを「自動的に」削除するのは驚くほど簡単です。それで、なぜそれをしませんか。

最初に実行する3つのステップ、次にいくつかの説明

1)Xcodeプロジェクトで、「yourProjectName-prefix.pch」ファイルを見つけます(通常、main.mファイルがあるグループ「supporting files」の下にあります)

2) '.pch'ファイルの最後に次の3行を追加します。

#ifndef DEBUG
   #define NSLog(...);
#endif

3)「デバッグ」バージョンと「リリース」バージョンの違いをテストします。これを行う1つの方法は、「スキームの編集」->「アプリ名の実行」->「情報」タブの下で、デバッグとリリースの間のドロップダウンボックスを使用して選択することです。リリースバージョンでは、デバッグコンソールにNSLog出力が表示されません!

これはどのように機能しますか?

まず第一に、プリプロセッサは比較的「ダム」であり、コンパイラが呼び出される前に「テキスト置換」として機能することを知っている必要があります。 '#define'を#defineステートメントに続くもので置き換えます。

#define NSLog(...);

(...)は、括弧()の間にある「何でも」を表します。最後に;にも注意してください。コンパイラがこれを最適化するため、これは厳密に必要ではありませんが、より「正しい」ので、そこに置くのが好きです。 #defineの後には 'nothing'があるため、プリプロセッサはそれを 'nothing'に置き換えます。したがって、NSLog...から;までの完全な行を破棄します。

#ifdef(定義されている場合)または#ifndef(定義されていない場合)を使用して、定義ステートメントを条件付きにすることができます。

ここでは#ifndef DEBUGを記述します。これは、「シンボルDEBUGが定義されていない場合」を意味します。 #ifdefまたは#ifndefは、#endifで「閉じる」必要があります

Xcode 5は、デビルドモードが「DEBUG」の場合、デフォルトで「DEBUG」シンボルを定義します。 「リリース」では、これは定義されていません。これをプロジェクト設定で確認できます。[ビルド設定]タブ-> [Apple LLVM 5.0-プリプロセッシング]セクションまでスクロールします->プリプロセッサマクロ。シンボル「DEBUG」はリリースビルド用に定義されていないことがわかります。

最後に、.pchファイルはXcodeによって自動的に作成され、コンパイル時にすべてのソースファイルに自動的に含まれます。したがって、#define全体を各ソースファイルに入れたかのようになります。

116
Ronny Webers

上記のほぼすべての答えは解決策を推測しますが、問題を説明するものではありません。私はグーグルで検索をして、その理由を見つけました。私の答えは次のとおりです。

はい、リリースバージョンでNSLogをコメントアウトすると、パフォーマンスが向上します。 NSLogはかなり遅いためです。なぜですか? NSLogは、1)ログメッセージをApple System Logging(ASL))に書き込みます。2)アプリがxcodeで実行されている場合、stderrにも書き込みます。

主な問題は最初の問題にあります。スレッドセーフを実現するために、NSLogが呼び出されるたびに、ASL機能への接続を開き、メッセージを送信し、接続を閉じます。接続操作は非常に高価です。もう1つの理由は、NSLogがタイムスタンプを取得してログに記録するのに時間がかかることです。

here からの参照。

31
Andrew

私の個人的なお気に入りは、可変長マクロを使用することです。

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif
23
Eytan

本番環境でNSLog()をまったく呼び出さないことが少し速くなると賢明にコメントしたすべての人々に加えて、私はそれを追加します:

これらのNSLog()出力文字列は、ストアからアプリをダウンロードし、Xcodeを実行しているMacに接続されたデバイスでアプリを実行するすべてのユーザーに表示されます(オーガナイザーウィンドウから)。

記録する情報に応じて(特に、アプリがサーバーにアクセスしたり、認証を行う場合など)、これは深刻なセキュリティ問題になる可能性があります

19
Nicolas Miari

Project Default Setting

Xcodeのプロジェクトの現在のデフォルト設定内では、NS_BLOCK_ASSERTIONSマクロはリリースバージョンで1に設定され、DEBUG=1 inデバッグバージョン。

だから、私は次の方法を好む。

// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.
// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.
#ifndef NS_BLOCK_ASSERTIONS
    #define _DEBUG
#endif

#ifdef _DEBUG
// for debug mode 
#define DLog(fmt,...) NSLog(@"%s " fmt, __FUNCTION, ##__VA_ARGS__) 
... /// something extra
#else
// for release mode
#define DLog(fmt,...) /* throw it away */
... /// something extra
#endif
13
AechoLiu

はい、無効にする必要があります。特に、コードの速度を最大化しようとしている場合。 NSLogging things left and rightは、他の開発者が掘り下げようとしているシステムログを汚染し、スピードクリティカルなコード(ループ内など)に大きな影響を与える可能性があります。 「30%の速度向上!」でアップデートをリリースしました。数週間後... ;-)

5
Ben Gotow

すべての良い答えですが、主にアプリの開発/テスト段階で使用することを検討できるもう1つの小さなトリックがあります。

また、コードの直接制御外の問題を示す可能性のあるメッセージではなく、デバッグコードのみを有効にする場合は、アプリリリースコードにも役立ちます。

トリック:

。mファイルの先頭に次の行を含めるだけで、.mファイルごとにNSLogをオフにできます

_#define NSLog(...)
_

注:do[〜#〜] not [〜#〜]これに.hファイルを置き、.mファイルのみ!

これは、代わりにプリプロセッサマクロを展開することにより、コンパイラにNSLog()を評価させるだけです。マクロは引数を取り除くだけです。

再びオンにしたい場合は、いつでも使用できます

_#undef NSLog
_

たとえば、次のようなことを行うことで、特定のメソッドグループの周りのNSLogへの呼び出しを防ぐことができます。

_#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog
_
5
unsynchronized

NSLogは遅いため、リリースビルドには使用しないでください。以下のような単純なマクロは、無効にする必要があるアサートとともに、それを無効にします。 NSLogをリリースビルドで使用することがあまり一般的ではない場合は、NSLogを直接呼び出します。 「-DNDEBUG」を「other c flags」ビルド設定に追加することを忘れないでください。

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif
3
papahabla

pchファイルで、#endifの前にこれを書き留めます

#define NSLog() //
2
Sandeep Saurabh

これはどうですか?

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    
0
roberto.buratti
var showDebugLogs = false;

    func DLog(format: String, args: CVarArgType...) {
        if showDebugLogs{
        println(String(format: format, arguments: args))
        }
    }

これは追加の引数も受け入れます。必要に応じて、showDebugLogsパラメーター値をtrueまたはfalseに設定します。

0
Zahur