NSLog विधि नाम और लाइन नंबर का प्रिंट आउट और सशर्त रूप से अक्षम कैसे करें?


446

मैं Xcode में डिबगिंग पर एक प्रस्तुति कर रहा हूं और NSLog का कुशलतापूर्वक उपयोग करने के बारे में अधिक जानकारी प्राप्त करना चाहूंगा।

विशेष रूप से, मेरे दो प्रश्न हैं:

  • क्या वर्तमान विधि के नाम / लाइन नंबर को आसानी से NSLog करने का एक तरीका है?
  • क्या रिलीज़ कोड के संकलन से पहले सभी NSLogs को "अक्षम" करने का एक तरीका है?

12
पहला सवाल जहां पसंदीदा (स्टार) अधिक हैं, फिर upvotes ... +1 ..
फहीम पारकर

जवाबों:


592

यहाँ 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__)

DLB वैरिएबल सेट होने पर डीबग मैक्रो केवल आउटपुट के लिए उपयोग किया जाता है (डीबग पुष्टि के लिए प्रोजेक्ट्स C झंडे में -DDEBUG)।

ALog हमेशा टेक्स्ट (नियमित NSLog की तरह) आउटपुट देगा।

आउटपुट (उदाहरण के लिए ALog (@ "हैलो वर्ल्ड") इस तरह दिखेगा:

-[LibraryController awakeFromNib] [Line 364] Hello world

आपके पास ## क्यों है? मैंने सोचा था कि यह एक साथ gluing तर्कों के लिए था, लेकिन आप कुछ भी करने के लिए gluing नहीं हैं।
केसबश

1
यह तर्कों के संभावित स्थूल विस्तार को रोकता है
डेडरिख

यह सामान्य रूप से मैक्रोज़ के साथ हो सकता है; कुछ मैक्रो कई लाइनों का उत्पादन करते हैं। हमेशा ब्रेसिज़ का उपयोग करने के लिए बस एक और तर्क ;-)।
मृत्युंजय

महान और cocos2d एपीआई का समान लॉग स्टेटमेंट है।
यूं ली

यह कैसे होता है जो नियंत्रण स्ट्रिंग में संलग्न होने का (@"%s [Line %d] " fmt)कारण बनता है fmt? मैंने इस सिंटैक्स को इस डिबग मैक्रो के अलावा नहीं देखा है।
रॉबर्ट एल्टमैन

141

मैंने लिया है DLogऔर ALogऊपर से, और जोड़ा है ULogजो एक UIAlertViewसंदेश उठाता है ।

संक्षेप में:

  • DLogNSLogDEBUG चर सेट होने पर ही आउटपुट देगा
  • ALog हमेशा की तरह उत्पादन होगा NSLog
  • ULogUIAlertViewDEBUG चर सेट होने पर ही दिखाएंगे
#ifdef DEBUG
# DLog (fmt, ...) को परिभाषित करें NSLog ((@ "% s [लाइन% d]" fmt), __PRETTY_FUNCTION__, __LINE__, ## __ VA_ARGS__);
#अन्य
# परिभाषित DLog (...)
#अगर अंत
#define ALog (fmt, ...) NSLog ((@ "% s [लाइन% d]" fmt), __PRETTY_FUNCTION__, __LINE__, ## __ VA_ARAR__;
#ifdef DEBUG
# उलोग को परिभाषित करें (fmt, ...) {UIAlertView * चेतावनी = [[UIAlertView आबंटित] initWithTitle: [NSString stringWithFormat: @ "% s \ n [पंक्ति% d]", __PRETTY_FUNCTION__, __LINE__] संदेश: NSSring स्ट्रिंग , ## __ VA_ARGS__] प्रतिनिधि: एनआईएल रद्द करेंबटनटिटेल: @ "ओके" अन्यबटनटन: नील]; [अलर्ट शो]; }
#अन्य
# उलोग को परिभाषित करें (...)
#अगर अंत

यह है जो ऐसा लग रहा है:

डिबग UIAlertView

+1 डिडेरिक


मैं अपना ALog + DLog कोड ULog के साथ भी बढ़ाने जा रहा हूं। बहुत उपयोगी।
नीयन

यह कोड Xcode 5.1 में अप्रयुक्त चर त्रुटि का कारण बनता है अगर DEBUG में नहीं चल रहा है :(
yonix

अर्धविराम के साथ कुछ #define निर्देश क्यों समाप्त होते हैं?
मॉन्स्टीउर

@Locutus तो आपको DLogबयान के बाद अर्धविराम नहीं लगाना होगा । यह उपयोगी है क्योंकि अगर आपने किया, रिलीज बिल्ड में, DLogकुछ भी नहीं करने के लिए संकलित किया गया है, और आपको अपने कोड में झूलने वाले अर्धविराम के साथ छोड़ दिया जाएगा। यह एक त्रुटि नहीं है, लेकिन यह एक चेतावनी फेंक सकता है, यह आपकी सेटिंग्स पर निर्भर करता है, अगर यह किसी अन्य अर्धविराम का अनुसरण करता है।
ज़ेव ईसेनबर्ग

74
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

और कोई लॉगिंग आउटपुट नहीं दिखा, हालांकि मुझे नहीं पता कि इसका कोई साइड इफेक्ट है या नहीं।


20

यहाँ डिबग स्थिरांक का एक बड़ा संग्रह जो हम उपयोग करते हैं। का आनंद लें।

// 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

19

एक नई चाल है कि कोई जवाब नहीं देते। आप 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

16

इस सवाल का मेरा जवाब मदद कर सकता है, ऐसा लगता है कि यह एक 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

क्योंकि आपने %sप्रारूप निर्दिष्ट किया था, जो Apple को -Wcstring-format-directive2015 में शुरू की गई क्लैंग चेतावनी से अलग करने और टालने की कोशिश कर रहा है
जेफ

13

सभी NSLogs को अक्षम करना, किसी को मैक्रो से एलर्जी के लिए, यहाँ कुछ ऐसा है जिसे आप भी संकलित कर सकते हैं:

void SJLog(NSString *format,...)
{
    if(LOG)
    {   
        va_list args;
        va_start(args,format);
        NSLogv(format, args);
        va_end(args);
    }
}

और, इसे लगभग NSLog की तरह उपयोग करें:

SJLog(@"bye bye NSLogs !");

इस ब्लॉग से: https://whackylabs.com/logging/ios/2011/01/19/ios-moving-in-and-out-of-nslogs/


11

उपरोक्त उत्तरों को पूरक करने के लिए, कुछ स्थितियों में NSLog के लिए प्रतिस्थापन का उपयोग करना काफी उपयोगी हो सकता है, खासकर जब डिबगिंग। उदाहरण के लिए, प्रत्येक पंक्ति पर सभी दिनांक और प्रक्रिया नाम / आईडी जानकारी से छुटकारा पाने से आउटपुट को अधिक पठनीय और तेजी से बूट किया जा सकता है।

निम्नलिखित लिंक सरल लॉगिंग ज्यादा अच्छे बनाने के लिए काफी उपयोगी बारूद प्रदान करता है।

http://cocoaheads.byu.edu/wiki/a-different-nslog


11

लाइन नंबर और क्लास प्रदर्शित करने के लिए अपने मौजूदा NSLogs को बदलना आसान है, जहां से उन्हें बुलाया जाता है। अपनी उपसर्ग फ़ाइल में कोड की एक पंक्ति जोड़ें:

#define NSLog(__FORMAT__, ...) NSLog((@"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)

3
यह भी खूब रही! तुम यह कैसे तेजी से करोगे?
uplearnedu.com

@AddisDev मुझे यह सबसे अच्छा लगता है। बहुत साफ और सरल। मैं केवल NSLog का उपयोग करता हूं। मुझे पता नहीं है कि DLog और Ulog वैसे भी क्या हैं! धन्यवाद। मतदान हुआ ...
चार्ल्स रॉबर्टसन

@AddisDev मुझे वास्तव में समझ नहीं आया कि Apple डिफ़ॉल्ट रूप से NSLog () में इस महत्वपूर्ण डेटा को क्यों नहीं जोड़ता है? विचित्र ...
चार्ल्स रॉबर्टसन

8

यह सरल है, उदाहरण के लिए

- (शून्य) applicationWillEnterForeground: (UIApplication *) आवेदन {

    NSLog(@"%s", __PRETTY_FUNCTION__);

}

आउटपुट: - [AppDelegate applicationWillEnterForeground:]


5

उपरोक्त उत्तरों के शीर्ष पर निर्माण, यहाँ है कि मैंने क्या किया और साथ आया। मेमोरी लॉगिंग को भी जोड़ा।

#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

4

DLog के अलावा नया। जारी एप्लिकेशन से डिबग को पूरी तरह से हटाने के बजाय, केवल इसे अक्षम करें। जब उपयोगकर्ता को समस्याएं होती हैं, जिसमें डीबगिंग की आवश्यकता होती है, तो बस यह बताएं कि रिलीज़ किए गए एप्लिकेशन में डीबग कैसे सक्षम करें और ईमेल के माध्यम से लॉग डेटा का अनुरोध करें।

लघु संस्करण: वैश्विक चर बनाएं (हां, आलसी और सरल समाधान) और DLog को इस तरह संशोधित करें:

BOOL myDebugEnabled = FALSE;
#define DLog(fmt, ...) if (myDebugEnabled) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

Jomnius iLessons पर लंबा उत्तर iLearned: कैसे डायनामिक डिबग लॉगिंग को विमोचित अनुप्रयोग में करें


3

कुछ समय के लिए मैं कई ऊपर से अपनाए गए मैक्रोज़ की साइट का उपयोग कर रहा हूं। कंसोल में लॉगिंग पर मेरा ध्यान केंद्रित है, नियंत्रित और फ़िल्टर्ड वर्बोसिटी पर जोर देने के साथ ; यदि आपको बहुत सी लॉग लाइन्स से ऐतराज नहीं है, लेकिन आसानी से उनमें से बैचों को चालू और बंद करना चाहते हैं, तो आपको यह उपयोगी लग सकता है।

सबसे पहले, मैं वैकल्पिक रूप से NSLog को प्रिंट के साथ बदल देता हूं जैसा कि @Rodrigo द्वारा ऊपर वर्णित है

#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.

मुझे लगता है कि प्रत्येक पंक्ति टाइप करने के कुछ अतिरिक्त पात्र हैं जो मैं कर सकता हूं

  1. पर या बंद टिप्पणी की एक पूरी श्रेणी स्विच करें (उदाहरण के लिए केवल उन मॉडल को रिपोर्ट करें)
  2. उच्च स्तर की संख्या के साथ ठीक विवरण पर रिपोर्ट या कम संख्या के साथ चिह्नित सबसे महत्वपूर्ण कॉल

मुझे यकीन है कि कई लोग इसे एक ओवरकिल का एक सा पाएंगे, लेकिन अगर कोई इसे अपने उद्देश्यों के अनुरूप पाता है तो बस ..

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.