2010-11-30 12 views
8

मेरे दोस्तों में से एक ने मुझे आईफोन ऐप्स में एनएसईएक्सप्शन का उपयोग न करने के लिए कहा। उन्होंने जो कारण दिया वह "प्रदर्शन बाधा" था। लेकिन मैं इसके बारे में आश्वस्त नहीं हूँ।आईफोन ऐप्स में एनएसईएक्सप्शन का उपयोग

क्या कोई मुझे पुष्टि कर सकता है कि हमें आईफोन ऐप में एनएसईएक्सप्शन का उपयोग करने से रोकना चाहिए? यदि आपके पास एनएसईएक्सप्शन का उपयोग करने के लिए सर्वोत्तम प्रथाएं हैं, तो कृपया उसे भी प्रदान करें।

अद्यतन:

यह link हमें ऐप्लिकेशन स्तर पर अपवाद संचालन उपयोग करने के लिए अनुरोध करता है। क्या किसी ने कभी ऐसा किया है? कृपया इसके फायदे और किसी भी अन्य प्रदर्शन हिट्स जो इसे बना सकते हैं, दें।

उत्तर

30

संक्षेप में:

अपवाद का प्रयोग न करें कुछ भी लेकिन अप्राप्य त्रुटियों

यह केवल उपयोग करने के लिए उचित है इंगित करने के लिए @ कोशिश/अप्राप्य त्रुटियों से निपटने के लिए @ पकड़। आईओएस या मैक ओएस एक्स पर संचालन जैसे नियंत्रण-प्रवाह करने के लिए @ फेंक/@ try/@ कैच का उपयोग करना कभी भी उचित नहीं होता है। फिर भी, सावधानी से विचार करें कि क्या आप एक अपरिवर्तनीय त्रुटि या बस क्रैश करने के संकेत के लिए अपवाद का उपयोग करना बेहतर कर रहे हैं (कॉल abort()); एक दुर्घटना अक्सर अधिक सबूत के पीछे छोड़ देता है।

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

सिस्टम फ्रेमवर्क कोड के माध्यम से फेंक दिया गया अपवाद का व्यवहार अपरिभाषित है।


आप "किसी भी अपवाद का व्यवहार प्रणाली के माध्यम से ढांचे कोड अपरिभाषित है फेंक दिया।" व्याख्या कर सकते हैं में विस्तार से?

निश्चित रूप से।

सिस्टम ढांचे एक डिजाइन का उपयोग करते हैं जहां किसी भी अपवाद को घातक, गैर-पुनर्प्राप्ति योग्य, त्रुटि माना जाता है; सभी उद्देश्यों और उद्देश्यों के लिए एक प्रोग्रामर त्रुटि। इस नियम के लिए बहुत सीमित अपवाद (हे) हैं।

इस प्रकार, उनके कार्यान्वयन में, सिस्टम ढांचे यह सुनिश्चित नहीं करेंगे कि अगर सिस्टम अपवाद कोड के माध्यम से एक अपवाद फेंक दिया जाता है तो सबकुछ ठीक से साफ हो जाता है। साइन अप अपवाद है, परिभाषा के अनुसार, अप्राप्य, सफाई की लागत का भुगतान क्यों करें?

your-code-1() 
    system-code() 
     your-code-2() 

यानी:

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

यदि your-code-2 एक अपवाद फेंकता है, तो अपवाद system-code से गुजरता है इसका मतलब है कि व्यवहार अपरिभाषित है; system-code आपके आवेदन को एक अपरिभाषित, संभावित रूप से क्रैश या डेटा-हानिकारक, राज्य में छोड़ सकता है या नहीं।

या, अधिक दृढ़ता से: आप your-code-2 में एक अपवाद फेंक नहीं सकते हैं, जिसे आप पकड़ सकते हैं और इसे your-code-1 में संभाल सकते हैं।

+0

क्या आप "सिस्टम फ्रेमवर्क कोड के माध्यम से फेंक दिए गए किसी भी अपवाद का व्यवहार अपरिभाषित है।" विस्तार से? – Krishnan

+0

प्रश्न अपडेट किया गया .... – Krishnan

+0

+1, यह अच्छा है। क्या आप कृपया मुझे बता सकते हैं कि अपवाद के बारे में मेरी धारणा सही नहीं है। अगर मैं विशेष अपवाद के मामले में एनएसईएक्सप्शन का उपयोग करता हूं (मान लीजिए कि ऐरे बाध्य है) तो यह लोड होता है अपवाद की पुष्टि के लिए सभी कक्षाएं। कृपया जवाब दें। – Ishu

0

आम तौर पर खुद से पूछें कि क्या आप किसी त्रुटि को सिग्नल करने का प्रयास कर रहे हैं, या क्या आपके पास वास्तव में असाधारण स्थिति है? यदि पूर्व, तो यह किसी भी प्रदर्शन मुद्दे, वास्तविक या कथित होने पर ध्यान दिए बिना एक बहुत बुरा विचार है। यदि उत्तरार्द्ध, यह निश्चित रूप से करने के लिए सही बात है।

+2

वास्तव में नहीं; आईओएस में अपवाद अप्राप्य त्रुटियों के लिए हैं। – bbum

+1

मेरे लिए, पुनर्प्राप्ति योग्य स्थितियां त्रुटियां हैं :) – jer

6

मैंने अपने काफी गहन audio app के लिए अपवाद हैंडलिंग का उपयोग किया है, जिसमें कोई समस्या नहीं है। बहुत अधिक पढ़ने और बेंचमार्किंग और डिस्सेप्लिब्स विश्लेषण के बाद, मैं विवादास्पद निष्कर्ष पर आया हूं कि उनका उपयोग करने के लिए कोई वास्तविक कारण नहीं है (समझदारी से) और पर्याप्त कारण नहीं है (एनएसईआरआर पॉइंटर पॉइंटर्स, अंतहीन सशर्त ... छी!)। फ़ोरम पर लोग जो कुछ कह रहे हैं वह सिर्फ ऐप्पल डॉक्स को दोहरा रहा है।

मैं this blog post में काफी विस्तार का एक सा में जाने लेकिन मैं अपने निष्कर्ष यहाँ की रूपरेखा तैयार करेंगे:

मिथक 1: @ कोशिश/@ पकड़/@ अंत में काफी महंगी है

(सीपीयू के संदर्भ में)

मेरे आईफोन 4 पर, 1 मिलियन अपवाद फेंकने और पकड़ने में लगभग 8.5 सेकंड लगते हैं। यह प्रत्येक के लिए केवल 8.5 माइक्रोसॉन्ड के बराबर है। अपने रीयलटाइम CoreAudio धागे में महंगा है? शायद थोड़ा सा (लेकिन आप कभी अपवाद नहीं फेंकेंगे ??), लेकिन यूआईएलर्ट में 8.5μs देरी से उपयोगकर्ता को यह बताते हुए कि उनकी फाइल खोलने में कोई समस्या थी, क्या यह ध्यान दिया जा रहा है?

मिथक 2: @try ब्लाकों 32 बिट iOS पर एक लागत

एप्पल डॉक्स और राज्य "64 बिट पर शून्य लागत @try ब्लॉक" की बात 32 बिट पड़ता है कि एक लागत है। एक छोटे बेंचमार्किंग और डिस्सेप्लर विश्लेषण से संकेत मिलता है कि 32 बिट आईओएस (एआरएम प्रोसेसर) पर भी शून्य लागत @ ट्री ब्लॉक हैं। क्या ऐप्पल का मतलब 32 बिट इंटेल कहना था?

मिथक 3: यह मैटर्स कि कोको फ़्रेमवर्क माध्यम से फेंक दिया अपवाद अपरिभाषित

हाँ, वे "अनिर्धारित" कर रहे हैं, लेकिन आप एप्पल ढांचे के माध्यम से वैसे भी फेंक क्या कर रहे हैं? बेशक ऐप्पल उन्हें आपके लिए संभाल नहीं करता है। पुनर्प्राप्ति योग्य त्रुटियों के लिए अपवाद हैंडलिंग को लागू करने का पूरा बिंदु उन्हें स्थानीय रूप से संभालना है - बस प्रत्येक-एकल-पंक्ति "स्थानीय रूप से" नहीं।

यहां एक एज केस NSObject:performSelectorOnMainThread:waitUntilDone: जैसी विधियों के साथ है। यदि बाद का पैरामीटर हां है, तो यह एक सिंक्रोनस फ़ंक्शन जैसा कार्य करता है जिसमें आपको कॉलिंग स्कोप तक अपवाद की अपवाद की अपेक्षा करने के लिए क्षमा किया जा सकता है।

///////////////////////////////////////////////////////////////////////// 
#pragma mark - l5CCThread 
///////////////////////////////////////////////////////////////////////// 

@interface l5CCThread : NSThread @end 

@implementation l5CCThread 

- (void)main 
{ 
    @try { 

     [self performSelectorOnMainThread:@selector(_throwsAnException) withObject:nil waitUntilDone:YES]; 

    } @catch (NSException *e) { 
     NSLog(@"Exception caught!"); 
    } 
} 
- (void)_throwsAnException { @throw [NSException exceptionWithName:@"Exception" reason:@"" userInfo:nil]; } 

@end 

///////////////////////////////////////////////////////////////////////// 
#pragma mark - l5CCAppDelegate 
///////////////////////////////////////////////////////////////////////// 

@implementation l5CCAppDelegate 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    l5CCThread *thd = [[l5CCThread alloc] init]; 
    [thd start]; 

    return YES; 
} 
// ... 

इस मामले अपवाद (मुख्य थ्रेड के रन पाश) अपनी पकड़ लापता और दुर्घटनाग्रस्त "कोको ढांचे के माध्यम से" से होकर गुजरेगा में: उदाहरण के लिए। आप आसानी से जीसीडी के dispatch_synch का उपयोग करके इस पर काम कर सकते हैं और इसमें ब्लॉक कॉल को विधि कॉल और कोई अपवाद हैंडलिंग डाल सकते हैं।

का उपयोग क्यों NSException खत्म हो चुका है NSError के

किसी को भी जो कभी मुख्य ऑडियो जैसे पुराने सी-आधारित चौखटे में से एक में काम किया है जानता है कि क्या एक घर का काम यह, जाँच से निपटने और रिपोर्टिंग त्रुटियों है। मुख्य लाभ @ try/@ catch और NSExceptions प्रदान करता है यह है कि आपका कोड क्लीनर बनाए रखें और बनाए रखना आसान हो।

कहें कि आपके पास फ़ाइल की 5 लाइनें हैं जो फ़ाइल पर काम करती हैं। प्रत्येक में से एक, कहें, 3 अलग-अलग त्रुटियों को फेंक सकता है (उदाहरण के लिए डिस्क स्पेस से बाहर, त्रुटि पढ़ें, आदि)। एक सशर्त में प्रत्येक पंक्ति को लपेटने के बजाय जो कोई वापसी मूल्य के लिए जांच करता है और फिर एनएसईआरआरआर पॉइंटर जांच को अन्य ओबीजेसी विधि (या बदतर, #define मैक्रो का उपयोग करता है!) का उपयोग करता है, तो आप में सभी 5 लाइनों को एक @try में लपेटते हैं और वहां प्रत्येक त्रुटि को संभाल लें। उन लाइनों के बारे में सोचें जिन्हें आप बचाएंगे!

एनएसईएक्सप्शन सबक्लास बनाने के द्वारा, आप आसानी से त्रुटि संदेशों को केंद्रीकृत कर सकते हैं, और अपने कोड को उनके साथ बिछाड़ने से बच सकते हैं। आप घातक प्रोग्रामर त्रुटियों (जैसे एनएसएएसएसर्ट) से अपने ऐप के "गैर-घातक" अपवादों को आसानी से अलग कर सकते हैं। आप "नाम" निरंतर (उपclass का नाम, "नाम") की आवश्यकता से भी बच सकते हैं।

यह सब के उदाहरण और मानक और disassembly के बारे में अधिक जानकारी के on this blog post रहे हैं ...

अपवाद प्लस कोशिश/पकड़/अंत में प्रतिमान (सी ++, जावा, पीएचपी काफी द्वारा प्रयोग किया जाता हर दूसरे प्रमुख भाषा है, रुबी, पायथन)। शायद पारानोआ को छोड़ने और इसे गले लगाने का समय भी ... कम से कम आईओएस में।

+6

यह सुझाव देना कि पुनर्प्राप्ति योग्य त्रुटियों के लिए एनएसईएक्सप्शन का उपयोग करना ठीक है और प्रवाह नियंत्रण गलत है। ढांचे स्पष्ट रूप से इसका समर्थन नहीं करते हैं। – bbum

+0

(अधिक महत्वपूर्ण) बिंदु बीबीएम के अलावा, मुझे मुश्किल समय लगता है कि कैसे लचीलापन में सुधार/पकड़ने की कोशिश की गई है: यदि आप जो भी चाहते हैं वह ठीक नहीं होता है, तो जल्दी और अक्सर लौटें। यदि आपके पास पकड़ने का कैस्केड है, तो यह बेहतर कैसे है? – danyowdee

+2

क्योंकि आप प्रत्येक त्रुटि प्रकार के हैंडलिंग को प्रत्येक पंक्ति के बजाय कोड के दिए गए ब्लॉक के लिए एक ही स्थान पर केंद्रीकृत करते हैं। –

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