2017-07-10 8 views
1

新しいロギングおよびアクティビティのトレースAPIのサポートを、最新バージョンをまだ採用していないユーザーの下位互換性を維持する方法でライブラリに追加しようとしています。 OS(iOSまたはmacOS)。私はロギングの各レベルごとにカスタムロギングマクロを定義しており、古いOSではNSLogに戻っています。私はこの問題を1つの問題で解決しました。下位互換性を維持しながらos_log APIを採用する

新しいAPIでは、ログ出力に表示する場合は、非定数、非スカラー値を明示的にpublicとマークする必要があります。これは次のように私のマクロの呼び出しが見えるものです:これはos_log(例えばiOSの後に10.0)を含んSDKと罰金コンパイル

UZKLogInfo("Reading file %{public}@ from archive", fileName); 

が、私は以前のバージョンでコンパイルするときに、私のマクロはNSLogにフォールバック

:「国民書式指定子注釈os_logの外()/ os_trace()

そして、このようなログ行印刷されたルックスを使用

:、私は、コンパイラの警告が表示されます

Reading file <decode: missing data> from archive 

これは私のマクロ定義の簡略版(のみinfo定義を含むと簡素化され、条件:

#if UNIFIED_LOGGING_SUPPORTED 
    @import os.log; 

    #define UZKLogInfo(format, ...) os_log_info(OS_LOG_DEFAULT, format, ##__VA_ARGS__); 
#else // Fall back to regular NSLog 
    #define UZKLogInfo(format, ...) NSLog(@format, ##__VA_ARGS__); 
#endif 

の「{公共}」テキスト(いくつかの種類を取り除くためにどのような方法があります文字列の置換?)formatからフォールバックの場合?または、ログに常に表示されているレベルの情報を放棄することなく、古いAPIと新しいAPIをサポートする別の方法がありますか?マクロを使用する必要があります(last year's WWDC session on the topicに従うか、そうでないとコールサイトのメタデータが失われます)

+0

「文字列置換のいくつかの種類が」聞こえますあなた自身の質問です。 NSStringは提供していますか? – CRD

+0

@CRDしかし、私が置き換えをしたいのは 'NSString'ではなく、ソースファイルからマクロに置かれたテキストです。メモリ内に割り当てられたオブジェクトではありません。プリプロセッサがどのような機能を利用できるのかよく分かりませんが、NSStringのメソッドを利用する方法はないと思います。 – Dov

+1

'@ format'はNSStringですが、文字列がプログラムで生成されているかどうかは関係ありません。リテラルでもNSStringです。コンパイル中に文字列を変更することはできませんが、実行時に変更することは可能です。マクロには 'NSLog'呼び出しが含まれています。メソッド呼び出しを含めることができます。 – CRD

答えて

2

マクロ内でNSStringを置き換え、その一部としてコンパイラの警告を抑制することを選択しました。各ラインのために行って、というよりも、グローバルファイル全体またはプロジェクトのためにそれは次のようになります。

#if UNIFIED_LOGGING_SUPPORTED 
    @import os.log; 

    #define UZKLogInfo(format, ...) os_log_info(OS_LOG_DEFAULT, format, ##__VA_ARGS__); 

#else // Fall back to regular NSLog 

    #define _removeLogFormatTokens(format) [@format stringByReplacingOccurrencesOfString:@"{public}" withString:@""] 
    #define _stringify(a) #a 
    #define _nsLogWithoutWarnings(format, ...) \ 
     _Pragma(_stringify(clang diagnostic push)) \ 
     _Pragma(_stringify(clang diagnostic ignored "-Wformat-nonliteral")) \ 
     _Pragma(_stringify(clang diagnostic ignored "-Wformat-security")) \ 
     NSLog(_removeLogFormatTokens(format), ##__VA_ARGS__); \ 
     _Pragma(_stringify(clang diagnostic pop)) 

    #define UZKLogInfo(format, ...) _nsLogWithoutWarnings(format, ##__VA_ARGS__); 
#endif 

そうみたいに呼ばれています:あなたが答えているよう

UZKLogInfo("Message: %@", anObjectToLog); 
+0

私はこれを行う方法についても考えてきました。共有してくれてありがとう。私が検討していることの1つは、古いバージョンを削除するのではなく、iOS 10以降のログフォーマットに{public}を追加することです。そうすれば、すでに持っているすべてのログステートメントを見つけて置き換える必要はありません。私たちのログデータは、そのまま「プライベート」になりません。私たちはそれがどうなるかを見ていきます。 – manroe

+0

私はあなたの '#if UNIFIED_LOGGING_SUPPORTED'ロジックが実際は何だったのか知りたいです。私はライブラリのコンパイル時にこの種のチェックを行う方法を知らない。サポートはデバイス上のiOSバージョンに基づいているからね。 – manroe

+0

@manroeええ、私はすべてのプラットフォームのOSバージョンをグループ化しています。あなたはそれをここに見ることができます:https://github.com/abbeycode/UnzipKit/commit/8cf48b84d4b67​​4467e774f3d1844e4008fedc7ad#diff-9b62aea6b32c19c0cc4f2ac623b5d6a4R21 – Dov

関連する問題