私はXcodeでデバッグに関するプレゼンテーションをしています、そしてNSLogを効率的に使うことについてもっと多くの情報を得たいと思います。
特に、2つ質問があります。
これが私がよく使うNSLogの周りの便利なマクロです。
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
# define DLog(...)
#endif
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
DLogマクロは、DEBUG変数が設定されている場合(デバッグ確認用のプロジェクトのCフラグの-DDEBUG)にのみ出力されます。
ALogは常にテキストを出力します(通常のNSLogのように)。
出力(例:ALog(@ "Hello world"))は次のようになります。
-[LibraryController awakeFromNib] [Line 364] Hello world
上からDLog
とALog
を取り出し、ULog
というメッセージを表示するUIAlertView
を追加しました。
要約する:
DLog
はNSLog
のように出力されます。ALog
は常にNSLog
のように出力されます。ULog
は、DEBUG変数が設定されている場合にのみUIAlertView
を表示します。#ifdef DEBUG #DLog(fmt、...)NSLog((@ "%s [行%d]" fmt)、__PRETTY_FUNCTION__、__LINE__、## __ VA_ARGS __); #else #define DLog(...) #endif #define ALog(fmt、...)NSLog((@ "%s [行%] d] "fmt)、__PRETTY_FUNCTION__、__LINE__、## __ VA_ARGS __); #ifdef DEBUG #ULog(fmt、...)を定義する{UIAlertView * alert = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:@ "%s\n [行%d]"、__PRETTY_FUNCTION__、__LINE__]メッセージ:[NSString stringWithFormat:fmt、## __ VA_ARGS__]デリゲート:nil cancelButtonTitle:@ "Ok" otherButtonTitles:nil]; [アラートショー]; } #else #define ULog(...) #endif
これはそれがどのように見えるかです:
+1ディーデリック
NSLog(@"%s %d %s %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, __FUNCTION__);
ファイル名、行番号、関数名を出力します:
/proj/cocoa/cdcli/cdcli.m 121 managedObjectContext managedObjectContext
__FUNCTION__
はC++でマングルされた名前を示します__PRETTY_FUNCTION__
は素敵な関数名を示します。ココアでは同じように見えます。
NSLogを無効にする適切な方法は何なのかわかりません。
#define NSLog
また、ログ出力は表示されませんでしたが、これに副作用があるかどうかはわかりません。
ここで私たちが使っているデバッグ定数の一つの大きなコレクション。楽しい。
// Uncomment the defitions to show additional info.
// #define DEBUG
// #define DEBUGWHERE_SHOWFULLINFO
// #define DEBUG_SHOWLINES
// #define DEBUG_SHOWFULLPATH
// #define DEBUG_SHOWSEPARATORS
// #define DEBUG_SHOWFULLINFO
// Definition of DEBUG functions. Only work if DEBUG is defined.
#ifdef DEBUG
#define debug_separator() NSLog( @"────────────────────────────────────────────────────────────────────────────" );
#ifdef DEBUG_SHOWSEPARATORS
#define debug_showSeparators() debug_separator();
#else
#define debug_showSeparators()
#endif
/// /// /// ////// /////
#ifdef DEBUG_SHOWFULLPATH
#define debug_whereFull() debug_showSeparators(); NSLog(@"Line:%d : %s : %s", __LINE__,__FILE__,__FUNCTION__); debug_showSeparators();
#else
#define debug_whereFull() debug_showSeparators(); NSLog(@"Line:%d : %s : %s", __LINE__,[ [ [ [NSString alloc] initWithBytes:__FILE__ length:strlen(__FILE__) encoding:NSUTF8StringEncoding] lastPathComponent] UTF8String ] ,__FUNCTION__); debug_showSeparators();
#endif
/// /// /// ////// /////
#define debugExt(args,...) debug_separator(); debug_whereFull(); NSLog( args, ##__VA_ARGS__); debug_separator();
/// /// /// ////// ///// Debug Print Macros
#ifdef DEBUG_SHOWFULLINFO
#define debug(args,...) debugExt(args, ##__VA_ARGS__);
#else
#ifdef DEBUG_SHOWLINES
#define debug(args,...) debug_showSeparators(); NSLog([ NSString stringWithFormat:@"Line:%d : %@", __LINE__, args ], ##__VA_ARGS__); debug_showSeparators();
#else
#define debug(args,...) debug_showSeparators(); NSLog(args, ##__VA_ARGS__); debug_showSeparators();
#endif
#endif
/// /// /// ////// ///// Debug Specific Types
#define debug_object( arg ) debug( @"Object: %@", arg );
#define debug_int( arg ) debug( @"integer: %i", arg );
#define debug_float( arg ) debug( @"float: %f", arg );
#define debug_rect( arg ) debug( @"CGRect ( %f, %f, %f, %f)", arg.Origin.x, arg.Origin.y, arg.size.width, arg.size.height );
#define debug_point( arg ) debug( @"CGPoint ( %f, %f )", arg.x, arg.y );
#define debug_bool( arg ) debug( @"Boolean: %@", ( arg == YES ? @"YES" : @"NO" ) );
/// /// /// ////// ///// Debug Where Macros
#ifdef DEBUGWHERE_SHOWFULLINFO
#define debug_where() debug_whereFull();
#else
#define debug_where() debug(@"%s",__FUNCTION__);
#endif
#define debug_where_separators() debug_separator(); debug_where(); debug_separator();
/// /// /// ////// /////
#else
#define debug(args,...)
#define debug_separator()
#define debug_where()
#define debug_where_separators()
#define debug_whereFull()
#define debugExt(args,...)
#define debug_object( arg )
#define debug_int( arg )
#define debug_rect( arg )
#define debug_bool( arg )
#define debug_point( arg )
#define debug_float( arg )
#endif
答えが出ない新しいトリックがあります。 printf
の代わりにNSLog
を使用できます。これはあなたにきれいなログを与えるでしょう:
NSLog
を使用すると、次のようになります。
2011-11-03 13:43:55.632 myApp[3739:207] Hello Word
しかしprintf
を使うとあなただけが得られます:
Hello World
このコードを使う
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(...) {}
#endif
この質問 に対する私の答えは助けになるかもしれませんが、Diederikが作ったものと似ているようです。 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
MACROSにアレルギーがある人のために、すべてのNSLogを無効にすると、ここでもコンパイルできるようになります。
void SJLog(NSString *format,...)
{
if(LOG)
{
va_list args;
va_start(args,format);
NSLogv(format, args);
va_end(args);
}
}
そして、NSLogのようにそれを使ってください。
SJLog(@"bye bye NSLogs !");
このブログから: http://whackylabs.com/rants/?p=134
上記の答えを補足するために、特定の状況で、特にデバッグ時にNSLogの代わりを使用することは非常に役に立ちます。たとえば、各行の日付とプロセス名/ ID情報をすべて削除すると、出力が読みやすくなり、起動が速くなります。
次のリンクは単純なロギングをより良くするためのかなりの役に立つ弾薬を提供します。
既存のNSLogを、それらが呼び出された行番号とクラスを表示するように変更するのは簡単です。プレフィックスファイルに1行のコードを追加します。
#define NSLog(__FORMAT__, ...) NSLog((@"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
それは簡単です、例えば
void)applicationWillEnterForeground:(UIApplication *)アプリケーション{
NSLog(@"%s", __PRETTY_FUNCTION__);
}
---(出力: - [AppDelegate applicationWillEnterForeground:]
上記の答えの上に構築して、これが私が盗用して思いついたものです。メモリロギングも追加されました。
#import <mach/mach.h>
#ifdef DEBUG
# define DebugLog(fmt, ...) NSLog((@"%s(%d) " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DebugLog(...)
#endif
#define AlwaysLog(fmt, ...) NSLog((@"%s(%d) " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#ifdef DEBUG
# define AlertLog(fmt, ...) { \
UIAlertView *alert = [[UIAlertView alloc] \
initWithTitle : [NSString stringWithFormat:@"%s(Line: %d) ", __PRETTY_FUNCTION__, __LINE__]\
message : [NSString stringWithFormat : fmt, ##__VA_ARGS__]\
delegate : nil\
cancelButtonTitle : @"Ok"\
otherButtonTitles : nil];\
[alert show];\
}
#else
# define AlertLog(...)
#endif
#ifdef DEBUG
# define DPFLog NSLog(@"%s(%d)", __PRETTY_FUNCTION__, __LINE__);//Debug Pretty Function Log
#else
# define DPFLog
#endif
#ifdef DEBUG
# define MemoryLog {\
struct task_basic_info info;\
mach_msg_type_number_t size = sizeof(info);\
kern_return_t e = task_info(mach_task_self(),\
TASK_BASIC_INFO,\
(task_info_t)&info,\
&size);\
if(KERN_SUCCESS == e) {\
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; \
[formatter setNumberStyle:NSNumberFormatterDecimalStyle]; \
DebugLog(@"%@ bytes", [formatter stringFromNumber:[NSNumber numberWithInteger:info.resident_size]]);\
} else {\
DebugLog(@"Error with task_info(): %s", mach_error_string(e));\
}\
}
#else
# define MemoryLog
#endif
DLogに新しく追加されました。リリースされたアプリケーションからデバッグを完全に削除するのではなく、無効にするだけです。ユーザが問題を抱えていてデバッグが必要な場合は、リリースされたアプリケーションでデバッグを有効にするそしてメールでログデータを要求する方法を教えてください。
ショートバージョン:グローバル変数を作成し(はい、怠惰で簡単な解決策)、DLogを次のように修正します。
BOOL myDebugEnabled = FALSE;
#define DLog(fmt, ...) if (myDebugEnabled) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
Jomnius iLessons iLearnedでの長い答え: リリースされたアプリケーションで動的デバッグログを記録する方法
私はしばらくの間、上記のいくつかから採用されたマクロのサイトを使用してきました。 制御されたフィルタリングされた冗長性に重点を置いて、コンソールへのログインに焦点を当てます。多くのログ行を気にしなくても、それらのバッチを簡単にオンおよびオフにしたい場合は、これが便利です。
まず、上記の@Rodrigoで説明されているように、NSLogをオプションでprintfに置き換えます。
#define NSLOG_DROPCHAFF//comment out to get usual date/time ,etc:2011-11-03 13:43:55.632 myApp[3739:207] Hello Word
#ifdef NSLOG_DROPCHAFF
#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#endif
次に、ログオンをオンまたはオフにします。
#ifdef DEBUG
#define LOG_CATEGORY_DETAIL// comment out to turn all conditional logging off while keeping other DEBUG features
#endif
メインブロックでは、アプリ内のモジュールに対応するさまざまなカテゴリを定義します。ロギングレベルも定義します。このレベルを超えると、ロギング呼び出しは呼び出されません。それからNSLog出力の様々なフレーバーを定義します。
#ifdef LOG_CATEGORY_DETAIL
//define the categories using bitwise leftshift operators
#define kLogGCD (1<<0)
#define kLogCoreCreate (1<<1)
#define kLogModel (1<<2)
#define kLogVC (1<<3)
#define kLogFile (1<<4)
//etc
//add the categories that should be logged...
#define kLOGIFcategory kLogModel+kLogVC+kLogCoreCreate
//...and the maximum detailLevel to report (use -1 to override the category switch)
#define kLOGIFdetailLTEQ 4
// output looks like this:"-[AppDelegate myMethod] log string..."
# define myLog(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s " format), __PRETTY_FUNCTION__, ##__VA_ARGS__);}
// output also shows line number:"-[AppDelegate myMethod][l17] log string..."
# define myLogLine(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s[l%i] " format), __PRETTY_FUNCTION__,__LINE__ ,##__VA_ARGS__);}
// output very simple:" log string..."
# define myLogSimple(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"" format), ##__VA_ARGS__);}
//as myLog but only shows method name: "myMethod: log string..."
// (Doesn't work in C-functions)
# define myLog_cmd(category,detailLevel,format,...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%@: " format), NSStringFromSelector(_cmd), ##__VA_ARGS__);}
//as myLogLine but only shows method name: "myMethod>l17: log string..."
# define myLog_cmdLine(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%@>l%i: " format), NSStringFromSelector(_cmd),__LINE__ , ##__VA_ARGS__);}
//or define your own...
// # define myLogEAGLcontext(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s>l%i (ctx:%@)" format), __PRETTY_FUNCTION__,__LINE__ ,[EAGLContext currentContext], ##__VA_ARGS__);}
#else
# define myLog_cmd(...)
# define myLog_cmdLine(...)
# define myLog(...)
# define myLogLine(...)
# define myLogSimple(...)
//# define myLogEAGLcontext(...)
#endif
したがって、kLOGIFcategoryおよびkLOGIFdetailLTEQの現在の設定では、次のように呼び出します。
myLogLine(kLogVC, 2, @"%@",self);
印刷しますが、これはしません
myLogLine(kLogGCD, 2, @"%@",self);//GCD not being printed
もしません
myLogLine(kLogGCD, 12, @"%@",self);//level too high
個々のログ呼び出しの設定を上書きしたい場合は、負のレベルを使用してください。
myLogLine(kLogGCD, -2, @"%@",self);//now printed even tho' GCD category not active.
私はそれからできるように私は各行をタイプすることの少数の余分な文字が価値があると思います
私は多くの人がこれをやり過ぎることになると確信していますが、万が一誰かが自分の目的に合っていると思った場合に備えて。