2008-11-19 11 views
154

मुझे इस साइट पर कुछ बार यह बताया गया था, लेकिन मैं यह सुनिश्चित करना चाहता था कि यह वास्तव में मामला है।क्या यह सच है कि किसी को उत्पादन कोड पर NSLog() का उपयोग नहीं करना चाहिए?

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

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

+7

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

+5

एनएसएलओजी() लगातार लूप के अंदर पूरी तरह से आपके प्रदर्शन को मार देगा। – willc2

उत्तर

195

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

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

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

+7

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

+15

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

+1

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

25

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

सिस्टम लॉग को कूड़े हुए अनुप्रयोग परेशान हैं, और गैर-व्यावसायिक रूप से आते हैं।

+13

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

+4

अन्य डेवलपर जो आप कर रहे हैं और नाराज होंगे । कुछ डेवलपर्स के साथ एंड्रॉइड की एक समान समस्या है जो एक उत्कृष्ट उत्तर के लिए वास्तव में खराब है https://plus.google.com/110166527124367568225/posts/h4jK38n4XYR –

11

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

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


Xcode में स्वत: (और उम्मीद) व्यवहार को प्राप्त करने के लिए:

परियोजना सेटिंग्स में, "बिल्ड" टैब पर जाएँ, और "डीबग" विन्यास का चयन करें। "प्रीप्रोसेसर मैक्रोज़" अनुभाग खोजें, और DEBUG_MODE नामक एक मैक्रो जोड़ें।

...

संपादित करें: सक्षम और DEBUG_MODE मैक्रो के साथ लॉगिंग अक्षम करने के लिए उचित तरीके के लिए Marc Charbonneau's answer देखें।

7

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

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

23

मैं Marc Charbonneau's answer पर टिप्पणी नहीं कर सकता, इसलिए मैं इसे एक उत्तर के रूप में पोस्ट करूंगा।

अपने पूर्व-संकलित शीर्षलेख में मैक्रो जोड़ने के लिए, आप परिभाषा (या परिभाषित करने की कमी) को नियंत्रित करने के लिए लक्ष्य निर्माण कॉन्फ़िगरेशन का उपयोग कर सकते हैं DEBUG_MODE

यदि आप "डीबग" सक्रिय विन्यास, DEBUG_MODE परिभाषित किया जाएगा, और स्थूल पूर्ण NSLog परिभाषा को विस्तृत करता है।

"रिलीज" का अर्थ सक्रिय विन्यास DEBUG_MODE को परिभाषित नहीं है और अपने NSLog ging रिलीज निर्माण से छोड़ा गया है।

कदम:

  • लक्ष्य> "Preprocessor मैक्रो" (या GCC_PREPROCESSOR_DEFINITIONS)
  • विन्यास का चयन के लिए जाओ जानकारी
  • बिल्ड टैब
  • खोज: डीबग
  • संपादित परिभाषा इस स्तर पर
  • जोड़े DEBUG_MODE=1
  • विन्यास का चयन करें: रिलीज
  • पुष्टि DEBUG_MODEGCC_PREPROCESSOR_DEFINITIONS

में सेट नहीं है अगर आप परिभाषा '=' चरित्र को छोड़ देते हैं, तो आप एक त्रुटि प्राप्त होगी पूर्वप्रक्रमक से

इसके अलावा, ऊपर मैक इस टिप्पणी (नीचे दिखाया गया) पेस्ट ro परिभाषा याद दिलाने के लिए जहां DEBUG_MACRO परिभाषित से आता है,)

// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS 
// Configuration = Release: <empty> 
//    = Debug: DEBUG_MODE=1 
+1

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

+0

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

+0

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

0

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

+0

किसी को ओवरहेड पर विचार करना चाहिए कि टेस्टफलाइट टी जोड़ता है ओ आवेदन। क्या टेस्टफलाइट के लॉगिंग हिस्से को जोड़ना संभव है? –

2

जैसा कि अन्य उत्तरों में बताया गया है, आप एनएसएलओजी का उपयोग या संशोधित समय पर नहीं बदलने के लिए # परिभाषा का उपयोग कर सकते हैं।

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

आपके कोड में डीएसएलओजीवीरबोज या डीडीएलओजीर इत्यादि द्वारा एनएसएलओजी को प्रतिस्थापित करें, मैक्रो परिभाषाओं के लिए # आयात जोड़ें और लॉगर्स को सेट करें, प्रायः एप्लिकेशनडिफिश लांचिंग विधि में।

NSLog के रूप में विन्यास कोड

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

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

2

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

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

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

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

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

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

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

75

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

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

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

+4

आपका उत्तर सबसे अच्छा है। – SpaceDog

+0

समस्या को हल करने का सबसे अच्छा और आसान तरीका +1 करता है। – rockXrock

+0

उत्तर –

4

सरल सत्य यह है कि एनएसएलओजी सिर्फ सादा धीमा है।

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

एनएसएलओजी वास्तव में क्या करता है?

यह लॉगिंग (ASL) सुविधा एप्पल प्रणाली को संदेश लॉग इन करें लिखते हैं:

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

एसटीडीईआरआर को लिखना मुश्किल नहीं है। यह fprintf और stderr फ़ाइल descriptor संदर्भ के साथ पूरा किया जा सकता है। लेकिन एएसएल के बारे में क्या?

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

बहुत ज्यादा विस्तार, मुख्य आकर्षण में जा रहा है (क्योंकि यह प्रदर्शन से संबंधित है) के बिना यह है:

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

संसाधन here & here पाया जा सकता है।

+0

रिलीज करने के लिए डीबग करें शीर्षलेख (शीर्षक) –

+0

पढ़ने के लिए मुश्किल मुझे मेरी खराब अंग्रेजी के लिए क्षमा करें। मैं चीनी में अच्छा हूं, लेकिन इसका उपयोग यहां नहीं कर सकता। – Andrew

+0

पाठ संपादित किया गया। संसाधन केवल पाद लेख में होने की आवश्यकता है। –

1

ध्यान रखें कि एनएसएलॉग यूआई/मुख्य धागे को धीमा कर सकते हैं। पूरी तरह जरूरी होने तक रिलीज बिल्ड से उन्हें हटाना सबसे अच्छा है।

संबंधित मुद्दे