क्या यह सच है कि किसी को उत्पादन कोड पर NSLog () का उपयोग नहीं करना चाहिए?


155

मुझे इस बहुत साइट में कुछ बार बताया गया था, लेकिन मैं यह सुनिश्चित करना चाहता था कि वास्तव में ऐसा ही हो।

मैं अपने पूरे कोड में NSLog फ़ंक्शन कॉल को छिड़कने में सक्षम होने की उम्मीद कर रहा था, और यह कि Xcode / gcc मेरी रिलीज़ / वितरण बिल्ड बनाते समय स्वचालित रूप से उन कॉल को हटा देगा।

क्या मुझे इसके इस्तेमाल से बचना चाहिए? यदि हां, तो अनुभवी उद्देश्य-सी प्रोग्रामर के बीच कौन से विकल्प सबसे आम हैं?


7
मुझे पता है कि यह प्रश्न अब बहुत पुराना है, लेकिन, यदि आप अभी भी कर सकते हैं, तो मैं मार्क चारबोन्यू के उत्तर को स्वीकार करूंगा। मैंने उसके उत्तर को इंगित करने के लिए अपना उत्तर संशोधित किया है, लेकिन उसका उत्तर सही है।
ई। जम्स

5
NSLog () लगातार लूप के अंदर आपके प्रदर्शन को पूरी तरह से खत्म कर देगा, उन्होंने कहा, कठिन रास्ते का पता लगाया।
willc2

जवाबों:


197

प्रीप्रोसेसर मैक्रोज़ वास्तव में डीबगिंग के लिए बहुत अच्छे हैं। 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

मुझे इस पूरे कथन को अपनी फ़ाइल के बजाय उपसर्ग शीर्षलेख में रखना आसान लगा। यदि आप चाहते थे, तो डिबग्लॉग सामान्य ऑब्जेक्ट-सी ऑब्जेक्ट के साथ सहभागिता करके अधिक जटिल लॉगिंग सिस्टम का निर्माण कर सकते थे। उदाहरण के लिए, आपके पास एक लॉगिंग वर्ग हो सकता है जो अपनी लॉग फ़ाइल (या डेटाबेस) को लिखता है, और इसमें एक 'प्राथमिकता' तर्क शामिल होता है जिसे आप रनटाइम पर सेट कर सकते हैं, इसलिए डिबग संदेश आपके रिलीज़ संस्करण में नहीं दिखाए जाते हैं, लेकिन त्रुटि संदेश हैं ( यदि आपने ऐसा किया है तो आप डिबग्लॉग (), वार्निंगलॉग (), और इसी तरह से बना सकते हैं।

ओह, और ध्यान रखें #define DEBUG_MODEकि आपके आवेदन में विभिन्न स्थानों पर फिर से उपयोग किया जा सकता है। उदाहरण के लिए, मेरे आवेदन में मैं लाइसेंस कुंजी जांच को अक्षम करने के लिए इसका उपयोग करता हूं और केवल एक निश्चित तिथि से पहले आवेदन को चलाने की अनुमति देता हूं। यह मुझे मेरी ओर से न्यूनतम प्रयास के साथ एक समय सीमित, पूरी तरह कार्यात्मक बीटा कॉपी वितरित करने देता है।


8
एक उत्कृष्ट जवाब के लिए +1। मैंने यह सूचित करने के लिए मेरा बदला है कि आपका #define मैक्रोज़ जाने का रास्ता है, और मुझे आशा है कि ओपी स्वीकार किए गए उत्तर को बदल देता है (मैंने उसे एक टिप्पणी छोड़ दी)। मैं एक डमी फ़ंक्शन का उपयोग कर रहा था क्योंकि मुझे नहीं पता था कि आप उपयोग कर सकते हैं ... मैक्रो में तर्क। जानने रहते हैं!
ई। जेमेश

15
एक उत्कृष्ट उत्तर, हालांकि मैं आपके "DEBUG_MODE" पर एक व्यक्तिगत उपसर्ग का उपयोग करने की सलाह देता हूं, जैसे कि इसे "JPM_DEBUG" या पसंद करना। बहुत बार मैंने तीसरे पक्ष के कोड का सामना किया है जो DEBUG या DEBUG_MODE या इस तरह का उपयोग करता है, और कभी-कभी यह कोड DEBUG मोड में सही ढंग से काम नहीं करेगा। यदि आप तृतीय-पक्ष लाइब्रेरी डीबगिंग चालू करना चाहते हैं, तो आपको ऐसा जानबूझकर करना चाहिए। (बेशक, यह पुस्तकालय लेखक हैं, जो अपने प्रतीकों को उपसर्ग करना चाहिए, लेकिन कई सी और सी ++ फ्रेमवर्क विशेष रूप से इस परिभाषित के लिए नहीं हैं)।
रॉब नेपियर

1
क्या कोई Xcode पूर्वनिर्धारित मैक्रो है जिसका उपयोग केवल इसे चालू करने के लिए किया जा सकता है जब कॉन्फ़िगरेशन डीबग करने के लिए सेट है? मैं नहीं बल्कि स्वयं ही इस प्रोजैक्टर मैक्रो को हर प्रोजेक्ट में स्वयं सेट करूँगा। क्या हम कुछ छद्मकोड #if XCODE_CONFIGURATION == DEBUG का अनुसरण कर सकते हैं?
फ्रैंककोडियर

1
#include <TargetConditionals.h>
slf

2
यह दृष्टिकोण रिलीज़ मोड में कंपाइलर से "अप्रयुक्त चर" चेतावनियों की ओर जाता है जब लॉगिंग स्टेटमेंट लॉग को मानों की गणना के एकमात्र उद्देश्य के लिए मध्यस्थ चर का उपयोग करते हैं। इससे बचने का सबसे स्मार्ट तरीका क्या होगा यदि आप कंपाइलर चेतावनियों से नफरत करते हैं जितना मैं करता हूं?
बजे जीन-डेनिस म्यूस सेप

78

इस 3 पंक्तियों को -prefix.pch फ़ाइल के अंत में रखें:

#ifndef DEBUG
  #define NSLog(...) /* suppress NSLog when in release mode */
#endif

आपको अपनी परियोजना में कुछ भी परिभाषित करने की आवश्यकता नहीं है, क्योंकि DEBUGजब आप अपना प्रोजेक्ट बनाते हैं तो डिफ़ॉल्ट रूप से आपकी बिल्ड सेटिंग में परिभाषित होता है।


2
सबसे अच्छा समाधान है। आपको XCode 6. से मैन्युअल रूप से उपसर्ग जोड़ने की आवश्यकता है।
Teddy

फिर भी हमें रिलीज से पहले बिल्ड सेटिंग बदलने की जरूरत है यानी रिलीज के लिए डिबग
UserDev

25

NSLog कॉल को उत्पादन कोड में छोड़ा जा सकता है, लेकिन वास्तव में असाधारण मामलों के लिए ही होना चाहिए, या जानकारी है कि यह वांछित है कि सिस्टम लॉग में लॉग किया जाएगा।

सिस्टम लॉग को अलग करने वाले अनुप्रयोग कष्टप्रद होते हैं, और अप्रमाणिक के रूप में सामने आते हैं।


14
क्षमा करें - किसके लिए लाभहीन के रूप में सामने आते हैं? किसी रिलीज़ किए गए ऐप पर आपके लॉग की जाँच करने और उसके आधार पर आपके व्यावसायिकता को पहचानने की संभावना कौन है? (स्पष्ट होने के लिए, मैं इस बात से पूरी तरह सहमत हूँ कि आपको अपने आवेदन के रिलीज़ संस्करण में एक टन NSLogs नहीं रखना चाहिए, लेकिन मैं 'व्यावसायिकता' के तर्क से भ्रमित हूँ।)
WendiKidd

4
अन्य डेवलपर्स आप क्या कर रहे हैं और नाराज हो जाते हैं। एंड्रॉइड में कुछ डेवलपर्स के साथ वास्तव में खराब होने की एक समान समस्या है। I11110166527124367568225
रोजर बिन्स

24

मैं मार्क चारबोन्यू के जवाब पर टिप्पणी नहीं कर सकता , इसलिए मैं इसे उत्तर के रूप में पोस्ट करूंगा।

मैक्रो को अपने पूर्व-संकलित हेडर में जोड़ने के लिए, आप लक्ष्य निर्धारण कॉन्फ़िगरेशन का उपयोग करके परिभाषित (या परिभाषित करने की कमी) को नियंत्रित कर सकते हैं 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

1
यह प्रश्न का एक मूल्यवान अतिरिक्त उत्तर है। टिप्पणी से अधिक होने का वर्णन करता है।
मॉर्निंगस्टार

DEBUG_MODEऔर DEBUG_MACROअपरंपरागत हैं। मुझे केवल DEBUG_MACROऐप्पल की साइट पर एक संदर्भ मिला है ( खुलता है ।ourceource.apple.com/source/gm4/gm4-15/src/m4.h?txt )। शायद अधिक मानक DEBUGऔर NDEBUGबेहतर विकल्प होंगे? NDEBUGPosix द्वारा निर्दिष्ट किया गया है; जबकि DEBUGसम्मेलन द्वारा उपयोग किया जाता है।
jww

+1 हाँ यह एक पुरानी पोस्ट है, लेकिन यह बात है ... मेरे Xcode के संस्करण में (4 साल बाद), GCC_PREPROCESSOR_DEFINITIONS की खोज कुछ अलग भाषा लौटाती है। कृपया स्पष्टता के लिए इस उत्कृष्ट उत्तर को अपडेट करने पर विचार करें।
डेविड

11

संपादित करें: विधि द्वारा पोस्ट की गई मार्क Charbonneau , और के आधार पर अपना ध्यान में लाया थानेदार , अब तक इस एक से बेहतर है।

मैंने अपने उत्तर के उस हिस्से को हटा दिया है जिसमें डीबग मोड अक्षम होने पर लॉगिंग को अक्षम करने के लिए एक खाली फ़ंक्शन का उपयोग करने का सुझाव दिया गया है। स्वचालित प्रीप्रोसेसर मैक्रो को सेट करने वाला भाग अभी भी प्रासंगिक है, इसलिए यह बना हुआ है। मैंने प्रीप्रोसेसर मैक्रो का नाम भी संपादित किया है ताकि यह मार्क चारबोन्यू के जवाब के साथ बेहतर रूप से फिट हो।


Xcode में स्वचालित (और अपेक्षित) व्यवहार प्राप्त करने के लिए:

प्रोजेक्ट सेटिंग्स में, "बिल्ड" टैब पर जाएं, और "डीबग" कॉन्फ़िगरेशन का चयन करें। "प्रीप्रोसेसर मैक्रोज़" अनुभाग ढूंढें, और नामित मैक्रो जोड़ें DEBUG_MODE

...

संपादित करें: मैक्रो के साथ लॉगिंग को सक्षम और अक्षम करने के उचित तरीके के लिए मार्क चारबोन्यू का जवाब देखें DEBUG_MODE


7

मैं मैथ्यू से सहमत हूं। उत्पादन कोड में NSLog के साथ कुछ भी गलत नहीं है। वास्तव में, यह उपयोगकर्ता के लिए उपयोगी हो सकता है। यदि आपने NSLog का उपयोग करने का एकमात्र कारण डिबग में मदद करना बताया है, तो, हां, आपको जारी करने से पहले हटा दिया जाना चाहिए।

इसके अलावा, जब से आपने इसे iPhone प्रश्न के रूप में टैग किया है, NSLog संसाधन लेता है, जो कि कुछ ऐसा है जिसमें iPhone कीमती है। यदि आप iPhone पर कुछ भी NSLogging कर रहे हैं , जो आपके ऐप से प्रोसेसर समय को दूर करता है। समझदारी से इस्तेमाल करो।


4

सरल सच यह है कि NSLog सिर्फ सादा धीमा है।

पर क्यों? उस प्रश्न का उत्तर देने के लिए, आइए जानें कि NSLog क्या करता है, और फिर यह कैसे करता है।

NSLog वास्तव में क्या करता है?

NSLog 2 काम करता है:

यह Apple सिस्टम लॉगिंग (asl) सुविधा के लिए लॉग संदेश लिखता है। यह लॉग संदेश को Console.app में दिखाने की अनुमति देता है। यह यह देखने के लिए भी जांचता है कि क्या एप्लिकेशन का स्टेडर स्ट्रीम टर्मिनल पर जा रहा है (जैसे कि जब एप्लिकेशन को Xcode के माध्यम से चलाया जा रहा है)। यदि ऐसा है तो यह लॉग संदेश को stderr पर लिखता है (ताकि यह Xcode कंसोल में दिखाई दे)।

STDERR को लिखना कठिन नहीं लगता है। यही कारण है कि fprintf और stderr फ़ाइल वर्णनकर्ता संदर्भ के साथ पूरा किया जा सकता है। लेकिन asl के बारे में क्या?

एएसएल के बारे में मैंने जो सबसे अच्छा प्रलेखन पाया है, वह पीटर होसी: लिंक से एक 10 भाग ब्लॉग पोस्ट है

बहुत अधिक विस्तार में जाने के बिना, हाइलाइट (जैसा कि यह प्रदर्शन की चिंता करता है) यह है:

ASL सुविधा में लॉग संदेश भेजने के लिए, आप मूल रूप से ASL डेमॉन के लिए क्लाइंट कनेक्शन खोलते हैं और संदेश भेजते हैं। लेकिन - प्रत्येक थ्रेड को एक अलग क्लाइंट कनेक्शन का उपयोग करना चाहिए। इसलिए, थ्रेड को सुरक्षित रखने के लिए, हर बार NSLog को कॉल करने पर यह एक नया एसएल क्लाइंट कनेक्शन खोलता है, संदेश भेजता है और फिर कनेक्शन बंद कर देता है।

संसाधन यहां और यहां पाए जा सकते हैं


पाठ को संपादित किया। संसाधनों को केवल पाद लेख में होना चाहिए।
जोहान कार्लसन ने

2

जैसा कि अन्य उत्तरों में उल्लेख किया गया है कि आप संकलन समय पर NSLog का उपयोग किया जाता है या नहीं, इसे बदलने के लिए #define का उपयोग कर सकते हैं।

हालाँकि एक अधिक लचीला तरीका यह है कि कोको लम्बरजैक जैसी लॉगिंग लाइब्रेरी का उपयोग किया जाए ताकि आप यह बदल सकें कि क्या कुछ रनटाइम में भी लॉग इन है।

अपने कोड में NSLog को DDLogVerbose या DDLogError आदि से बदलें, मैक्रो डेफिनेशन आदि के लिए एक #import जोड़ें और अक्सर एप्लिकेशनDidFinishLaunching विधि में, लॉगर्स को सेटअप करें।

NSLog के समान प्रभाव के लिए कॉन्फ़िगरेशन कोड है

[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];

2

सुरक्षा के दृष्टिकोण से, यह निर्भर करता है कि क्या लॉग किया जा रहा है। यदि NSLog(या अन्य लॉगर) संवेदनशील जानकारी लिख रहा है, तो आपको उत्पादन कोड में लकड़हारे को हटा देना चाहिए।

ऑडिटिंग दृष्टिकोण से, ऑडिटर NSLogअपनी संवेदनशील जानकारी को लॉग इन नहीं करने के लिए सुनिश्चित करने के लिए प्रत्येक उपयोग को देखना नहीं चाहता है । वह / आपको बस लकड़हारे को हटाने के लिए कहेगा।

मैं दोनों समूहों के साथ काम करता हूं। हम कोड का ऑडिट करते हैं, कोडिंग गाइड लिखते हैं, आदि हमारे गाइड को आवश्यकता होती है कि लॉगिंग उत्पादन कोड में अक्षम हो। इसलिए आंतरिक टीमें इसे आजमाना नहीं जानती;)

कि उत्पादन में लॉग क्योंकि हम नहीं गलती से लीक संवेदनशील जानकारी के साथ जुड़े जोखिम को स्वीकार करना चाहते हम भी एक बाहरी एप्लिकेशन को अस्वीकार कर देंगे। हमें परवाह नहीं है कि डेवलपर हमें क्या बताता है। इसकी जांच करने के लिए हमारे समय के लायक नहीं है।

और याद रखें, हम 'संवेदनशील' को परिभाषित करते हैं, न कि डेवलपर को;)

मैं एक ऐप भी समझता हूं, जो एक ऐप को प्रत्यारोपण के लिए तैयार के रूप में बहुत सारे लॉगिंग करता है। वहाँ एक कारण इतना लॉगिंग किया जाता है / जरूरत है, और इसकी आम तौर पर स्थिरता नहीं है। 'राइटडॉग' धागे के साथ इसका अधिकार है जो त्रिशंकु सेवाओं को फिर से शुरू करता है।

यदि आप एक सुरक्षा वास्तुकला (SecArch) की समीक्षा के माध्यम से कभी नहीं गए हैं, तो ये उन चीजों के प्रकार हैं जिन्हें हम देखते हैं।


1

आपको रिलीज़ कोड में प्रिंटफ या NSLog के साथ अनावश्यक रूप से क्रिया नहीं करनी चाहिए। केवल एक प्रिंटफ या NSLog करने की कोशिश करें यदि ऐप में कुछ बुरा है, तो यह एक अपरिवर्तनीय त्रुटि है।


1

ध्यान रखें कि NSLogs UI / मुख्य थ्रेड को धीमा कर सकते हैं। जब तक बिल्कुल आवश्यक न हो, उन्हें रिलीज़ बिल्ड से निकालना सबसे अच्छा है।


0

मैं अत्यधिक लॉगिंग (मुक्त) के लिए TestFlight का उपयोग करने की सलाह दूंगा। उनका तरीका NSLog (मैक्रो का उपयोग करके) को ओवरराइड करेगा और आपको NSLog में आपके सभी मौजूदा कॉल के लिए उनके सर्वर, Apple सिस्टम लॉग और STDERR लॉग को चालू / बंद करने की अनुमति देगा। इसके बारे में अच्छी बात यह है कि आप अभी भी उपयोगकर्ता के सिस्टम लॉग पर दिखाई देने वाले लॉग के बिना, ऐप स्टोर में परीक्षकों और ऐप पर तैनात ऐप के लिए अपने लॉग संदेशों की समीक्षा कर सकते हैं। दोनों दुनिया के सर्वश्रेष्ठ।


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