जवाबों:
कुछ चीजें हैं जो मैंने करना शुरू कर दिया है, मुझे नहीं लगता कि मानक हैं:
1) गुणों के आगमन के साथ, मैं अब "निजी" वर्ग चर को उपसर्ग करने के लिए "_" का उपयोग नहीं करता हूं। आखिरकार, अगर एक चर को अन्य वर्गों द्वारा एक्सेस किया जा सकता है, तो क्या इसके लिए कोई संपत्ति नहीं होनी चाहिए? मैंने हमेशा "_" उपसर्ग को कोड बदसूरत बनाने के लिए नापसंद किया, और अब मैं इसे छोड़ सकता हूं।
2) निजी चीजों की बात करें, तो मैं एक वर्ग विस्तार में .m फ़ाइल के भीतर निजी पद्धति की परिभाषाएँ देना पसंद करता हूँ:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
बाहरी लोगों के साथ .h फ़ाइल की अव्यवस्था क्यों परवाह नहीं करनी चाहिए? खाली () .m फ़ाइल में निजी श्रेणियों के लिए काम करता है, और यदि आप घोषित तरीकों को लागू नहीं करते हैं तो चेतावनी जारी करते हैं।
3) मैंने @synthesize निर्देशों के ठीक नीचे .m फ़ाइल के शीर्ष पर Dealloc लगाने के लिए लिया है। क्या आपको उन चीजों की सूची में शीर्ष पर नहीं होना चाहिए जो आप कक्षा में सोचना चाहते हैं? यह iPhone जैसे वातावरण में विशेष रूप से सच है।
3.5) तालिका कोशिकाओं में, प्रदर्शन के लिए प्रत्येक तत्व (सेल स्वयं सहित) अपारदर्शी बनाते हैं। इसका मतलब है कि हर चीज में उपयुक्त बैकग्राउंड कलर सेट करना।
3.6) NSURLConnection का उपयोग करते समय, एक नियम के रूप में आप प्रतिनिधि पद्धति को लागू करना चाहते हैं:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
मुझे लगता है कि अधिकांश वेब कॉल बहुत विलक्षण हैं और यह उस नियम से अधिक अपवाद है, जिसे आप खासतौर पर वेब सेवा कॉल के लिए प्रतिसाद दे रहे हैं। दिखाए गए तरीके को लागू करना प्रतिक्रियाओं के कैशिंग को अक्षम करता है।
रुचि के अलावा, जोसेफ मैटिएलो (iPhone मेलिंग सूची में प्राप्त) से कुछ अच्छे iPhone विशिष्ट सुझाव हैं। वहाँ अधिक हैं, लेकिन ये सबसे आम तौर पर मुझे लगा कि उपयोगी थे (ध्यान दें कि कुछ बिट्स अब मूल से थोड़ा संपादित किए गए हैं ताकि प्रतिक्रियाओं में शामिल विवरणों को शामिल किया जा सके):
4) यदि आपको कोरलोकेशन के साथ काम करना हो तो केवल डबल प्रिसिजन का उपयोग करें। यह सुनिश्चित करें कि आप अपने स्थिरांक को 'f' में समाप्त करते हैं ताकि gcc को फ्लोट के रूप में संग्रहीत किया जा सके।
float val = someFloat * 2.2f;
यह ज्यादातर महत्वपूर्ण है जब someFloat
वास्तव में एक डबल हो सकता है, आपको मिश्रित-मोड गणित की आवश्यकता नहीं है, क्योंकि आप भंडारण पर 'वैल' में सटीक खो रहे हैं। जबकि फ्लोटिंग-पॉइंट नंबर iPhones पर हार्डवेयर में समर्थित हैं, फिर भी एकल परिशुद्धता के विपरीत डबल-सटीक अंकगणित करने में अधिक समय लग सकता है। संदर्भ:
माना जाता है कि पुराने फोन एक ही गति से काम करते हैं, लेकिन आप डबल्स की तुलना में रजिस्टरों में अधिक एकल सटीक घटक रख सकते हैं, इसलिए कई गणनाओं के लिए एकल परिशुद्धता तेजी से समाप्त हो जाएगी।
5) अपने गुण सेट करें nonatomic
। वे atomic
डिफ़ॉल्ट रूप से और संश्लेषण पर, मल्टी-थ्रेडिंग समस्याओं को रोकने के लिए सेमाफोर कोड बनाया जाएगा। आप में से 99% को शायद इस बारे में चिंता करने की आवश्यकता नहीं है और कोड गैर-परमाणु पर सेट होने पर बहुत कम फूला हुआ और अधिक स्मृति-कुशल है।
6) SQLite बड़े डेटा सेट को कैश करने का एक बहुत तेज़ तरीका हो सकता है। उदाहरण के लिए एक मानचित्र एप्लिकेशन अपनी टाइलों को SQLite फ़ाइलों में कैश कर सकता है। सबसे महंगा हिस्सा डिस्क I / O है। बड़े ब्लॉकों को भेजकर BEGIN;
और उनके COMMIT;
बीच कई छोटे लेखन से बचें । हम प्रत्येक नए सबमिट पर रीसेट करने वाले उदाहरण के लिए 2 सेकंड के टाइमर का उपयोग करते हैं। जब यह समाप्त हो जाता है, तो हम COMMIT भेजते हैं; , जो आपके सभी लेखन को एक बड़े हिस्से में जाने का कारण बनता है। SQLite लेन-देन के डेटा को डिस्क में संग्रहीत करता है और यह आरंभ / समाप्ति रैपिंग कई लेनदेन फ़ाइलों के निर्माण से बचती है, सभी लेनदेन को एक फ़ाइल में समूहीकृत करता है।
इसके अलावा, SQL आपके GUI को ब्लॉक कर देगा यदि यह आपके मुख्य धागे पर है। यदि आपके पास बहुत लंबी क्वेरी है, तो अपने प्रश्नों को स्थिर वस्तुओं के रूप में संग्रहीत करना और अपनी SQL को एक अलग थ्रेड पर चलाना एक अच्छा विचार है। @synchronize() {}
ब्लॉक में क्वेरी स्ट्रिंग के लिए डेटाबेस को संशोधित करने वाली किसी भी चीज़ को लपेटना सुनिश्चित करें । लघु प्रश्नों के लिए सिर्फ आसान सुविधा के लिए मुख्य थ्रेड पर चीजों को छोड़ दें।
अधिक SQLite अनुकूलन युक्तियां यहां हैं, हालांकि दस्तावेज़ पुराना दिखाई देता है, जिनमें से कई बिंदु अभी भी अच्छे हैं;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
जब तरीके या फ़ंक्शंस एक प्रारूप स्ट्रिंग तर्क लेते हैं, तो आपको यह सुनिश्चित करना चाहिए कि प्रारूप स्ट्रिंग की सामग्री पर आपका नियंत्रण है।
उदाहरण के लिए, स्ट्रिंग्स को लॉग करते समय, यह स्ट्रिंग चर को एकमात्र तर्क के रूप में पास करने के लिए लुभाता है NSLog
:
NSString *aString = // get a string from somewhere;
NSLog(aString);
इसके साथ समस्या यह है कि स्ट्रिंग में ऐसे अक्षर हो सकते हैं जिन्हें प्रारूप स्ट्रिंग के रूप में व्याख्या किया जाता है। इससे गलत आउटपुट, क्रैश और सुरक्षा समस्याएं हो सकती हैं। इसके बजाय, आपको स्ट्रिंग चर को प्रारूप स्ट्रिंग में स्थान देना चाहिए:
NSLog(@"%@", aString);
मानक कोको नामकरण और स्वरूपण सम्मेलनों और शब्दावली का उपयोग करें जो आप किसी अन्य वातावरण से उपयोग किए जाते हैं। वहाँ कोको डेवलपर्स के बहुत सारे हैं , और जब उनमें से एक आपके कोड के साथ काम करना शुरू कर देता है, तो यह अन्य कोको कोड के समान दिखता है और लगता है तो यह बहुत अधिक स्वीकार्य होगा।
क्या करना है और क्या नहीं इसके उदाहरण हैं:
id m_something;
किसी ऑब्जेक्ट के इंटरफ़ेस में घोषित न करें और इसे एक सदस्य चर या फ़ील्ड कहें ; उपयोग something
या _something
इसके नाम के लिए और इसे एक उदाहरण चर कहते हैं ।-getSomething
; उचित कोको नाम सिर्फ है -something
।-something:
; यह होना चाहिए-setSomething:
-[NSObject performSelector:withObject:]
नहीं है NSObject::performSelector
।जो कुछ भी आप करते हैं, Win16 / Win32 शैली हंगेरियन संकेतन का उपयोग न करें। यहां तक कि Microsoft ने .NET प्लेटफ़ॉर्म की ओर कदम बढ़ाया।
ऐतिहासिक रूप से, आउटलेट का मेमोरी प्रबंधन खराब रहा है। वर्तमान सर्वोत्तम प्रथा को आउटलेट्स को गुणों के रूप में घोषित करना है:
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
गुणों का उपयोग करने से स्मृति प्रबंधन शब्दार्थ स्पष्ट हो जाता है; यदि आप उदाहरण चर संश्लेषण का उपयोग करते हैं तो यह एक सुसंगत पैटर्न भी प्रदान करता है।
नोट: Xcode 4 के तहत यह अब IDE में बनाया गया है।
आप मैक ओएस एक्स 10.5 पर क्लैंग स्टेटिक एनालाइज़र से - बिना - - अपने सी और ऑब्जेक्टिव-सी कोड (अभी तक कोई सी ++) का विश्लेषण नहीं करते हैं। यह स्थापित करने और उपयोग करने के लिए तुच्छ है:
cd
आपकी परियोजना निर्देशिका तक।scan-build -k -V xcodebuild
।(कुछ अतिरिक्त बाधाएं हैं आदि, विशेष रूप से आपको इसके "डिबग" कॉन्फ़िगरेशन में एक परियोजना का विश्लेषण करना चाहिए - विवरण के लिए http://clang.llvm.org/StaticAnalysisUsage.html देखें - लेकिन यह अधिक-या-कम है यह क्या उबलता है।)
विश्लेषक तब आपके लिए वेब पेजों का एक सेट तैयार करता है, जो संभावित मेमोरी प्रबंधन और अन्य बुनियादी समस्याओं को दर्शाता है जो कंपाइलर का पता लगाने में असमर्थ है।
यह सूक्ष्म है, लेकिन एक काम है। यदि आप स्वयं को किसी अन्य ऑब्जेक्ट के प्रतिनिधि के रूप में पास कर रहे हैं, तो उस ऑब्जेक्ट के प्रतिनिधि को आपके सामने रीसेट करें dealloc
।
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
ऐसा करने से आप सुनिश्चित कर रहे हैं कि कोई और प्रतिनिधि विधियाँ नहीं भेजी जाएँगी। जैसा कि आप के बारे में है dealloc
और ईथर में गायब हो जाते हैं आप यह सुनिश्चित करना चाहते हैं कि कुछ भी दुर्घटना से आपको कोई संदेश नहीं भेज सकता है। स्वयं को याद रखें। किसी अन्य वस्तु के द्वारा (यह एक सिंगलटन हो सकता है या ऑटोरेलिज़ पूल या जो भी हो) को बनाए रखा जा सकता है और जब तक आप यह नहीं बताते हैं कि "मुझे संदेश भेजना बंद करो!", यह आपके न्यायसंगत व्यवहार के बारे में सोचता है। उचित खेल है।
इस आदत में शामिल होने से आपको बहुत सारी अजीब दुर्घटनाओं से बचाया जा सकता है जो डीबग करने के लिए एक दर्द हैं।
मुख्य मूल्य मुख्य मूल्य अवलोकन पर लागू होता है, और NSNotifications भी।
संपादित करें:
और भी अधिक रक्षात्मक, परिवर्तन:
self.someObject.delegate = NULL;
में:
if (self.someObject.delegate == self)
self.someObject.delegate = NULL;
Memory Management Programming Guide for Cocoa
: Additional cases of weak references in Cocoa include, but are not restricted to, table data sources, outline view items, notification observers, and miscellaneous targets and delegates. In most cases, the weak-referenced object is aware of the other object’s weak reference to it, as is the case for circular references, and is responsible for notifying the other object when it deallocates.
nil == NULL
। वे वास्तव में एक ही हैं सिवाय इसके कि nil
एक है id
और NULL
एक है void *
। आपका कथन सत्य नहीं है।
@kendell
के बजाय:
@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end
उपयोग:
@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end
ऑब्जेक्टिव-सी 2.0 में नया।
क्लास एक्सटेंशन को Apple के ऑब्जेक्टिव-सी 2.0 संदर्भ में वर्णित किया गया है।
"क्लास एक्सटेंशन आपको प्राथमिक वर्ग @interface ब्लॉक के अलावा अन्य स्थानों में एक वर्ग के लिए अतिरिक्त आवश्यक एपीआई घोषित करने की अनुमति देता है"
इसलिए वे वास्तविक वर्ग का हिस्सा हैं - और वर्ग के अतिरिक्त (निजी) श्रेणी नहीं। सूक्ष्म लेकिन महत्वपूर्ण अंतर।
()
बजाय उपयोग करने के लिए एक महत्वपूर्ण लाभ है (Private)
: आप संपत्तियों को फिर से लिखना के रूप में पढ़ सकते हैं जबकि जनता के लिए वे केवल पठनीय हैं। :)
चूंकि आप आमतौर पर (1) अपने जीवनकाल पर सीधा नियंत्रण नहीं रखते हैं, ऑटोरेल्ड ऑब्जेक्ट्स तुलनात्मक रूप से लंबे समय तक बने रह सकते हैं और अनावश्यक रूप से आपके एप्लिकेशन की मेमोरी फ़ुटप्रिंट को बढ़ा सकते हैं। डेस्कटॉप पर जब तक यह कम परिणाम हो सकता है, अधिक विवश प्लेटफार्मों पर यह एक महत्वपूर्ण मुद्दा हो सकता है। सभी प्लेटफार्मों पर, इसलिए, और विशेष रूप से अधिक विवश प्लेटफार्मों पर, यह उन तरीकों का उपयोग करने से बचने के लिए सबसे अच्छा अभ्यास माना जाता है जो ऑटोरेल्ड ऑब्जेक्ट को ले जाएंगे और इसके बजाय आपको आवंटित / इनिट पैटर्न का उपयोग करने के लिए प्रोत्साहित किया जाता है।
इस प्रकार, इसके बजाय:
aVariable = [AClass convenienceMethod];
जहां सक्षम हो, आपको इसके बजाय उपयोग करना चाहिए:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
जब आप अपनी खुद की विधियाँ लिख रहे होते हैं जो एक नई बनाई गई वस्तु को लौटाते हैं, तो आप कोको के नामकरण कन्वेंशन का फ़ायदा उठाकर रिसीवर को फ़्लैग कर सकते हैं कि इसे "नया" विधि नाम के साथ जोड़कर जारी किया जाना चाहिए।
इस प्रकार, इसके बजाय:
- (MyClass *)convenienceMethod {
MyClass *instance = [[[self alloc] init] autorelease];
// configure instance
return instance;
}
आप लिख सकते हैं:
- (MyClass *)newInstance {
MyClass *instance = [[self alloc] init];
// configure instance
return instance;
}
चूंकि विधि का नाम "नए" से शुरू होता है, आपके एपीआई के उपभोक्ताओं को पता है कि वे प्राप्त वस्तु को जारी करने के लिए जिम्मेदार हैं (देखें, उदाहरण के लिए, NSObjectController की newObject
विधि )।
(1) आप अपने स्वयं के स्थानीय ऑटोरेलिज पूल का उपयोग करके नियंत्रण ले सकते हैं। इस पर अधिक जानकारी के लिए, ऑटोरेलिज पूल देखें ।
NSAutoreleasePool
। लेकिन आपके द्वारा पुष्टि किए जाने के बाद ही कि यह वास्तव में एक मुद्दा है। समयपूर्व अनुकूलन और वह सब ...
इनमें से कुछ का उल्लेख पहले ही किया जा चुका है, लेकिन यहां मैं अपने शीर्ष के शीर्ष के बारे में सोच सकता हूं:
#pragma mark [section]
। आमतौर पर मैं अपने तरीकों से समूह, प्रत्येक उपवर्ग के ओवरराइड्स, और किसी भी जानकारी या औपचारिक प्रोटोकॉल। यह एक बहुत आसान करने के लिए मैं क्या देख रहा हूँ कूद करने के लिए बनाता है। एक ही विषय पर, समूह समान विधियाँ (जैसे तालिका दृश्य की प्रतिनिधि विधियाँ) एक साथ होती हैं, बस उन्हें कहीं भी न रखें।#define
भी डेटा की आवश्यकता होती है, तो इसे हर बार छाँटने के बजाय एक सरणी बनाना या एक सरणी को कैशिंग करना होगा। इस बारे में मैं बहुत कुछ कह सकता हूं, लेकिन नीचे की पंक्ति कोड को तब तक नहीं लिखती जब तक आपको इसकी आवश्यकता नहीं होती, या प्रोफाइलर आपको बताता है। यह लंबे समय में चीजों को बनाए रखना आसान बनाता है।NSLog( @"stub" )
अंदर डालकर इंगित करें , या हालांकि आप चीजों का ट्रैक रखना चाहते हैं।Finish what you start
आपके संबंध में आप // TODO:
कोड को पूरा करने के लिए उपयोग कर सकते हैं जो ड्रॉप डाउन में दिखाई देगा।
इकाई परीक्षण लिखें। आप कोको में बहुत सी चीजों का परीक्षण कर सकते हैं जो अन्य रूपरेखाओं में कठिन हो सकती हैं। उदाहरण के लिए, यूआई कोड के साथ, आप आम तौर पर यह सत्यापित कर सकते हैं कि चीजें जुड़ी हुई हैं क्योंकि उन्हें होना चाहिए और विश्वास है कि जब वे काम करेंगे। और आप उन्हें परखने के लिए आसानी से राज्य और प्रतिनिधि प्रतिनिधि विधियों की स्थापना कर सकते हैं।
आपके पास अपने आंतरिक के लिए परीक्षण लिखने के तरीके में सार्वजनिक बनाम संरक्षित बनाम निजी पद्धति दृश्यता नहीं है।
गोल्डन रूल: यदि आप alloc
तो आप release
!
अद्यतन: जब तक आप एआरसी का उपयोग नहीं कर रहे हैं
copy
, mutableCopy
, new
या retain
।
Objective-C को ऐसे न लिखें जैसे कि यह Java / C # / C ++ / etc था।
मैंने एक बार देखा कि जावा ईई वेब एप्लिकेशन लिखने के लिए इस्तेमाल की जाने वाली एक टीम ने कोको डेस्कटॉप एप्लिकेशन लिखने की कोशिश की। मानो यह एक जावा ईई वेब अनुप्रयोग था। वहाँ बहुत सारे AbstractFooFactory और FooFactory और IFoo और Foo के चारों ओर उड़ रहा था जब वे वास्तव में जरूरत थी एक Foo वर्ग और संभवतः एक Fooable प्रोटोकॉल था।
यह सुनिश्चित करने के लिए कि आप ऐसा नहीं करते हैं, यह वास्तव में भाषा के अंतर को समझ रहा है। उदाहरण के लिए, आपको ऊपर दिए गए अमूर्त कारखाने और फैक्ट्री कक्षाओं की आवश्यकता नहीं है क्योंकि ऑब्जेक्टिव-सी क्लास के तरीकों को डायनेमिक रूप से उदाहरण के तरीकों के रूप में भेजा जाता है, और उपवर्गों में ओवरराइड किया जा सकता है।
सुनिश्चित करें कि आप डिबगिंग मैजिक पेज को बुकमार्क कर लें । कोको बग के स्रोत को खोजने की कोशिश करते समय दीवार के खिलाफ अपना सिर पीटते समय यह आपका पहला पड़ाव होना चाहिए।
उदाहरण के लिए, यह आपको बताएगा कि उस पद्धति को कैसे खोजना है जहां आपने पहले मेमोरी आवंटित की थी जो बाद में क्रैश (जैसे ऐप समाप्ति के दौरान) हो रही है।
इससे बचने का प्रयास करें कि मैंने अब क्या Newbiecategoryaholism को बुलाने का फैसला किया है। जब नवागंतुक उद्देश्य-सी श्रेणियों को खोजते हैं, तो वे अक्सर जंगली हो जाते हैं, अस्तित्व में हर वर्ग के लिए उपयोगी छोटी श्रेणियों को जोड़ते हैं ( "क्या? मैं एक संख्या को रोमन संख्याओं को NSNumber रॉक पर बदलने के लिए जोड़ सकता हूं!" )।
यह मत करो।
आपका कोड अधिक पोर्टेबल और दो दर्जन नींव वर्गों के शीर्ष पर छिड़के गए छोटे श्रेणी के दर्जनों तरीकों के साथ समझने में आसान होगा।
अधिकांश समय जब आप वास्तव में सोचते हैं कि आपको कुछ कोड को सुव्यवस्थित करने में मदद के लिए एक श्रेणी विधि की आवश्यकता है, तो आप पाएंगे कि आप कभी भी विधि का पुन: उपयोग नहीं कर पाएंगे।
अन्य खतरे भी हैं, जब तक कि आप अपनी श्रेणी के तरीकों को नाम नहीं दे रहे हैं (और जो पूरी तरह से पागल ddribin के अलावा है?) वहाँ एक मौका है कि Apple, या एक प्लगइन, या आपके पते की जगह में चल रहे कुछ और भी उसी को परिभाषित करेंगे? एक ही नाम के साथ विधि थोड़ा अलग साइड इफेक्ट के साथ ....
ठीक। अब जब आपको चेतावनी दी गई है, तो "इस भाग को न करें" को अनदेखा करें। लेकिन अत्यधिक संयम बरतें।
दुनिया को उपवर्ग का विरोध करना। कोको में बहुत कुछ प्रतिनिधिमंडल और अंतर्निहित रनटाइम के उपयोग के माध्यम से किया जाता है जो कि अन्य ढांचे में उपवर्ग के माध्यम से किया जाता है।
उदाहरण के लिए, जावा में आप अनाम *Listener
उपवर्गों के उदाहरणों का उपयोग करते हैं और .NET में आप अपने EventArgs
उपवर्गों का बहुत अधिक उपयोग करते हैं । कोको में, आप या तो नहीं करते हैं - इसके बजाय लक्ष्य-क्रिया का उपयोग किया जाता है।
जब आप उपयोगकर्ता को प्रस्तुत करने के लिए तार छाँटते हैं, तो आपको सरल compare:
विधि का उपयोग नहीं करना चाहिए । इसके बजाय, आपको हमेशा स्थानीयकृत तुलना विधियों का उपयोग करना चाहिए जैसे कि localizedCompare:
या localizedCaseInsensitiveCompare:
।
अधिक जानकारी के लिए, खोज, तुलना और छंटनी स्ट्रिंग्स देखें ।
आपको आमतौर पर अपने सभी गुणों के लिए ऑब्जेक्टिव-सी 2.0 डिक्लेयरड प्रॉपर्टीज फीचर का उपयोग करना चाहिए। यदि वे सार्वजनिक नहीं हैं, तो उन्हें एक क्लास एक्सटेंशन में जोड़ें। घोषित संपत्तियों का उपयोग करने से स्मृति प्रबंधन शब्दार्थ तुरंत स्पष्ट हो जाता है, और इससे आपको अपनी डीललोक विधि की जांच करने में आसानी होती है - यदि आप अपनी संपत्ति की घोषणाओं को एक साथ जोड़ते हैं, तो आप उन्हें जल्दी से स्कैन कर सकते हैं और अपनी डीललोक विधि के कार्यान्वयन के साथ तुलना कर सकते हैं।
गुणों को 'गैर-परमाणु' के रूप में चिह्नित नहीं करने से पहले आपको कठिन सोचना चाहिए। के रूप में उद्देश्य सी प्रोग्रामिंग भाषा गाइड नोट, गुण डिफ़ॉल्ट रूप से परमाणु रहे हैं, और अपने ऊपर लेना काफी भूमि के ऊपर। इसके अलावा, बस अपने सभी गुणों को परमाणु बनाने से आपका एप्लिकेशन थ्रेड-सुरक्षित नहीं होता है। यह भी ध्यान दें, कि अगर आप 'नॉनटोमिक' निर्दिष्ट नहीं करते हैं और अपने स्वयं के एक्सेसर तरीकों को लागू करते हैं (बजाय उन्हें संश्लेषित करने के), तो आपको उन्हें एक परमाणु फैशन में लागू करना होगा।
जैसा कि यह प्रश्न नोट करता है, nil
उद्देश्य-सी में संदेश मान्य हैं। जबकि यह अक्सर एक फायदा है - क्लीनर और अधिक प्राकृतिक कोड के लिए अग्रणी - सुविधा कभी-कभी अजीबोगरीब और मुश्किल-से-ट्रैक-डाउन बग तक ले जा सकती है यदि आपको कोई nil
मूल्य मिलता है जब आप इसकी उम्मीद नहीं कर रहे थे।
NSAssert और दोस्तों का उपयोग करें। मैं हर समय वैध वस्तु के रूप में nil का उपयोग करता हूं ... विशेष रूप से nil को संदेश भेजना Obj-C में पूरी तरह से मान्य है। हालांकि अगर मैं वास्तव में एक चर की स्थिति के बारे में सुनिश्चित करना चाहता हूं, तो मैं NSAssert और NSParameterAssert का उपयोग करता हूं, जो समस्याओं को आसानी से ट्रैक करने में मदद करता है।
सरल लेकिन अक्सर भूल जाने वाला। युक्ति के अनुसार:
सामान्य तौर पर, विभिन्न वर्गों में विधियाँ जिनका चयनकर्ता (समान नाम) होता है, को भी समान रिटर्न और तर्क प्रकार साझा करने होंगे। इस बाधा को गतिशील बाध्यकारी की अनुमति देने के लिए संकलक द्वारा लगाया जाता है।
जिस स्थिति में, सभी समान नाम वाले चयनकर्ता, भले ही विभिन्न वर्गों में हों , समान रिटर्न / तर्क प्रकार माना जाएगा। ये रहा एक सरल उदाहरण।
@interface FooInt:NSObject{}
-(int) print;
@end
@implementation FooInt
-(int) print{
return 5;
}
@end
@interface FooFloat:NSObject{}
-(float) print;
@end
@implementation FooFloat
-(float) print{
return 3.3;
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
id f1=[[FooFloat alloc]init];
//prints 0, runtime considers [f1 print] to return int, as f1's type is "id" and FooInt precedes FooBar
NSLog(@"%f",[f1 print]);
FooFloat* f2=[[FooFloat alloc]init];
//prints 3.3 expectedly as the static type is FooFloat
NSLog(@"%f",[f2 print]);
[f1 release];
[f2 release]
[pool drain];
return 0;
}
यदि आप तेंदुए का उपयोग कर रहे हैं (Mac OS X 10.5) या बाद में, आप मेमोरी लीक को खोजने और ट्रैक करने के लिए इंस्ट्रूमेंट्स एप्लिकेशन का उपयोग कर सकते हैं। Xcode में अपना प्रोग्राम बनाने के बाद, रन> प्रदर्शन टूल से शुरू करें> लीक चुनें।
यहां तक कि अगर आपका ऐप कोई लीक नहीं दिखाता है, तो आप वस्तुओं को बहुत लंबे समय तक रख सकते हैं। इंस्ट्रूमेंट्स में, आप इसके लिए ObjectAlloc इंस्ट्रूमेंट का उपयोग कर सकते हैं। अपने इंस्ट्रूमेंट्स डॉक्यूमेंट में ObjectAlloc इंस्ट्रूमेंट को चुनें, और व्यू> डिटेल को चुनकर इंस्ट्रूमेंट की डिटेल (अगर यह पहले से नहीं दिखा रहा है) लाएँ (इसके आगे एक चेक मार्क होना चाहिए)। ObjectAlloc विस्तार में "आवंटन जीवनकाल" के तहत, सुनिश्चित करें कि आप "निर्मित और फिर भी जीवित" के बगल में रेडियो बटन चुनते हैं।
अब जब भी आप अपने एप्लिकेशन को रिकॉर्ड करना बंद करते हैं, तो ObjectAlloc टूल का चयन आपको यह दिखाएगा कि "# नेट" कॉलम में आपके आवेदन में प्रत्येक अभी भी जीवित ऑब्जेक्ट के कितने संदर्भ हैं। सुनिश्चित करें कि आप न केवल अपनी कक्षाओं को देखते हैं, बल्कि आपके एनआईबी फाइलों के शीर्ष स्तर की वस्तुओं को भी देखते हैं। उदाहरण के लिए, यदि आपके पास स्क्रीन पर कोई विंडो नहीं है, और आप अभी भी रहने वाले NSWindow के संदर्भ देखते हैं, तो हो सकता है कि आपने इसे अपने कोड में जारी नहीं किया हो।
डीलॉक में सफाई करें।
यह सबसे आसान चीजों में से एक है - जासूसी। जब 150mph पर कोडिंग। डीललोक में हमेशा, हमेशा, हमेशा अपनी विशेषताओं / सदस्य चर को साफ करें।
- मैं ObjC 2 विशेषताओं का उपयोग करना चाहते के साथ नई डॉट नोटेशन - तो यह सफाई दर्द रहित बनाता है। अक्सर के रूप में सरल:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
यह आपके लिए रिलीज़ की देखभाल करेगा और NULL को विशेषता सेट करेगा (जो मैं रक्षात्मक प्रोग्रामिंग पर विचार करता हूं - यदि किसी अन्य विधि में आगे प्रेषण में सदस्य चर को फिर से एक्सेस करता है - दुर्लभ लेकिन ऐसा हो सकता है)।
10.5 पर जीसी चालू होने के साथ, इसकी इतनी अधिक आवश्यकता नहीं है - लेकिन आपको अभी भी आपके द्वारा बनाए गए अन्य संसाधनों को साफ करने की आवश्यकता हो सकती है, आप इसे अंतिम विधि के बजाय कर सकते हैं।
-init
और -dealloc
तरीकों यहां पाया जा सकता है: mikeash.com/?page=pyblog/...
ये सभी टिप्पणियां बहुत अच्छी हैं, लेकिन मैं वास्तव में हैरान हूं कि किसी ने Google के उद्देश्य-सी स्टाइल गाइड का उल्लेख नहीं किया है जो कुछ समय पहले प्रकाशित हुआ था। मुझे लगता है कि उन्होंने बहुत गहन काम किया है।
इसके अलावा, अर्ध-संबंधित विषय (अधिक प्रतिक्रियाओं के लिए कमरे के साथ!):
उन छोटी Xcode युक्तियों और ट्रिक्स को क्या आप चाहते हैं कि आप 2 साल पहले जानते थे? ।
यह मत भूलो कि NSWindowController और NSViewController NIB फ़ाइलों के शीर्ष-स्तरीय ऑब्जेक्ट को वे जारी करेंगे जो वे शासन करते हैं।
यदि आप मैन्युअल रूप से एक एनआईबी फ़ाइल लोड करते हैं, तो आप उस एनआईबी के शीर्ष-स्तरीय ऑब्जेक्ट को जारी करने के लिए जिम्मेदार हैं जब आप उनके साथ काम करते हैं।
शुरुआत के लिए एक स्पष्ट रूप से एक का उपयोग करने के लिए: अपने कोड के लिए Xcode के ऑटो-इंडेंटेशन सुविधा का उपयोग करें। यहां तक कि अगर आप कोड को किसी अन्य स्रोत से कॉपी / पेस्ट कर रहे हैं, तो एक बार कोड को पेस्ट करने के बाद, आप कोड के पूरे ब्लॉक का चयन कर सकते हैं, उस पर राइट क्लिक करें, और फिर उस ब्लॉक के भीतर सब कुछ फिर से इंडेंट करने का विकल्प चुनें।
Xcode वास्तव में उस अनुभाग के माध्यम से पार्स करेगा और इसे कोष्ठक, लूप, आदि के आधार पर इंडेंट करेगा। यह प्रत्येक और हर पंक्ति के लिए स्पेस बार या टैब कुंजी मारने की तुलना में बहुत अधिक कुशल है।
मुझे पता है कि जब मैंने पहली बार कोको प्रोग्रामिंग में देखा तो मैंने इसे अनदेखा कर दिया।
सुनिश्चित करें कि आप एनआईबी फाइलों के संबंध में स्मृति प्रबंधन जिम्मेदारियों को समझते हैं। आपके द्वारा लोड की गई किसी भी एनआईबी फ़ाइल में शीर्ष-स्तरीय ऑब्जेक्ट जारी करने के लिए आप जिम्मेदार हैं। विषय पर Apple का दस्तावेज़ीकरण पढ़ें ।
सभी जीसीसी चेतावनियों को चालू करें, फिर उन लोगों को बंद करें जो नियमित रूप से एप्पल के हेडर के कारण शोर को कम करते हैं।
क्लैंग स्टैटिक विश्लेषण भी अक्सर चलाएं; आप इसे "रन स्टेटिक एनालाइज़र" बिल्ड सेटिंग के माध्यम से सभी बिल्ड के लिए सक्षम कर सकते हैं।
इकाई परीक्षण लिखें और उन्हें प्रत्येक बिल्ड के साथ चलाएं।
चर और गुण
1 / अपने हेडर को साफ रखना, कार्यान्वयन को छिपाना आपके हेडर
में उदाहरण चर शामिल नहीं है। निजी चर गुण के रूप में वर्ग निरंतरता में डालते हैं। सार्वजनिक चर आपके शीर्ष लेख में सार्वजनिक गुणों के रूप में घोषित होते हैं। यदि इसे केवल पढ़ा जाना चाहिए, तो इसे आसानी से घोषित करें और इसे कक्षा में निरंतरता के रूप में रीडराइट के रूप में अधिलेखित करें। मूल रूप से मैं चर का उपयोग नहीं कर रहा हूँ, केवल गुण।
2 / अपने गुणों को एक गैर-डिफ़ॉल्ट चर नाम दें, उदाहरण:
@synthesize property = property_;
कारण 1: आप "स्वयं" को भूलकर होने वाली त्रुटियों को पकड़ लेंगे। संपत्ति सौंपते समय। कारण 2: मेरे प्रयोगों से, लीक एनालाइज़र इन इंस्ट्रूमेंट्स में डिफ़ॉल्ट नाम के साथ लीक संपत्ति का पता लगाने में समस्याएं हैं।
3 / कभी भी संपत्तियों पर सीधे (या केवल बहुत ही असाधारण स्थितियों में) रिटेन या रिलीज का उपयोग न करें। अपने डील-डॉक में बस उन्हें एक शून्य असाइन करें। रिटेन प्रॉपर्टीज अपने आप से रिटेन / रिलीज को संभालने के लिए होती हैं। आप कभी नहीं जानते कि क्या कोई सेटर नहीं है, उदाहरण के लिए, पर्यवेक्षकों को जोड़ना या निकालना। आपको चर का उपयोग सीधे इसके सेटर और गेट्टर के अंदर करना चाहिए।
दृश्य
1 / प्रत्येक दृश्य परिभाषा को एक जिब में डालें, यदि आप कर सकते हैं (अपवाद आमतौर पर गतिशील सामग्री और परत सेटिंग्स है)। यह समय बचाता है (कोड लिखना आसान है), इसे बदलना आसान है और यह आपके कोड को साफ रखता है।
2 / विचारों की संख्या कम करके विचारों को अनुकूलित करने का प्रयास न करें। केवल Xib के बजाय अपने कोड में UIImageView न बनाएं क्योंकि आप इसमें सबव्यू जोड़ना चाहते हैं। इसके बजाय पृष्ठभूमि के रूप में UIImageView का उपयोग करें। व्यू फ्रेमवर्क समस्याओं के बिना सैकड़ों विचारों को संभाल सकता है।
3 / IBOutlets हमेशा बनाए रखने की जरूरत नहीं है (या मजबूत)। ध्यान दें कि आपके अधिकांश IBOutlets आपके दृश्य पदानुक्रम का हिस्सा हैं और इस प्रकार अंतर्निहित रूप से बनाए रखा गया है।
4 / देखें सभी IBOutlets को व्यूडाउन में लोड करें
5 / कॉल देखें अपने प्रोलोक विधि से देखें। इसे अंतर्निहित नहीं कहा जाता है।
याद
जब आप उन्हें बनाते हैं तो 1 / ऑटोरेलिज़ ऑब्जेक्ट। आपकी रिलीज़ कॉल को एक-और शाखा में या एक वापसी विवरण के बाद स्थानांतरित करने के कारण कई कीड़े होते हैं। ऑटोरेलिज़ के बजाय रिलीज़ को केवल असाधारण स्थितियों में उपयोग किया जाना चाहिए - जैसे जब आप एक रनलूप की प्रतीक्षा कर रहे हैं और आप नहीं चाहते कि आपकी वस्तु बहुत जल्दी ऑटोरेल्ड हो जाए।
2 / यहां तक कि अगर आप प्रामाणिक संदर्भ गणना का उपयोग कर रहे हैं, तो आपको पूरी तरह से समझना होगा कि कैसे-जारी करने के तरीके काम करते हैं। मैन्युअल रूप से री-रिलीज़ का उपयोग करना एआरसी से अधिक जटिल नहीं है, दोनों ही मामलों में आपको लीक और रिटेक-साइकल के बारे में बात करनी होगी। बड़ी परियोजनाओं या जटिल ऑब्जेक्ट पदानुक्रमों पर मैन्युअल रूप से री-रिलीज़ का उपयोग करने पर विचार करें।
टिप्पणियाँ
1 / अपने कोड को ऑटोडेक्नोलेटेड बनाएं। प्रत्येक चर नाम और विधि नाम को बताना चाहिए कि वह क्या कर रहा है। यदि कोड सही तरीके से लिखा गया है (आपको इसमें बहुत अभ्यास की आवश्यकता है), तो आपको किसी भी कोड टिप्पणी (प्रलेखन टिप्पणियों के समान नहीं) की आवश्यकता नहीं होगी। एल्गोरिदम जटिल हो सकता है लेकिन कोड हमेशा सरल होना चाहिए।
2 / कभी-कभी, आपको एक टिप्पणी की आवश्यकता होगी। आमतौर पर एक गैर स्पष्ट कोड व्यवहार या हैक का वर्णन करने के लिए। यदि आपको लगता है कि आपको कोई टिप्पणी लिखनी है, तो पहले कोड को सरल बनाने के लिए और टिप्पणियों की आवश्यकता के बिना उसे फिर से लिखने का प्रयास करें।
खरोज
1 / बहुत अधिक इंडेंटेशन न बढ़ाएं। आपके अधिकांश विधि कोड विधि स्तर पर इंडेंट होने चाहिए। नेस्टेड ब्लॉक (यदि, आदि के लिए) पठनीयता कम हो जाती है। यदि आपके पास तीन नेस्टेड ब्लॉक हैं, तो आपको आंतरिक ब्लॉकों को एक अलग विधि में डालने का प्रयास करना चाहिए। चार या अधिक नेस्टेड ब्लॉकों का उपयोग कभी नहीं किया जाना चाहिए। यदि आपका अधिकांश विधि कोड if के अंदर है, तो if दशा को नकारें, उदाहरण:
if (self) {
//... long initialization code ...
}
return self;
if (!self) {
return nil;
}
//... long initialization code ...
return self;
C कोड को समझना, मुख्य रूप से C संरचना
ध्यान दें कि ओब्ज-सी, सी भाषा पर केवल एक हल्की ओओपी परत है। आपको समझना चाहिए कि सी काम में बुनियादी कोड संरचनाएं (एनम, स्ट्रक्चर, एरे, पॉइंटर्स आदि) कैसे हैं। उदाहरण:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);
के समान है:
CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;
और बहुत सारे
अपने स्वयं के कोडिंग मानकों के दस्तावेज़ों को बनाए रखें और इसे अक्सर अपडेट करें। अपने कीड़े से सीखने की कोशिश करें। समझें कि एक बग क्यों बनाया गया था और कोडिंग मानकों का उपयोग करके इससे बचने की कोशिश करें।
हमारे कोडिंग मानकों में वर्तमान में लगभग 20 पृष्ठ हैं, जावा कोडिंग मानकों का मिश्रण है, Google Obj-C / C ++ मानक और हमारे स्वयं के जोड़ हैं। अपने कोड का दस्तावेज़, मानक मानक इंडेंटेशन, सफेद रिक्त स्थान और सही स्थानों पर रिक्त लाइनों आदि का उपयोग करें।
अधिक कार्यात्मक बनें ।
ऑब्जेक्टिव-सी ऑब्जेक्ट-ओरिएंटेड लैंग्वेज है, लेकिन कोको फ्रेमवर्क फंक्शनल-स्टाइल अवेयर है, और कई मामलों में फंक्शनल स्टाइल डिजाइन किया गया है।
उत्परिवर्तन का पृथक्करण है। प्राथमिक के रूप में अपरिवर्तनीय कक्षाओं का उपयोग करें , और माध्यमिक के रूप में परिवर्तनशील वस्तु। उदाहरण के लिए, मुख्य रूप से NSArray का उपयोग करें, और जब आवश्यक हो तभी NSMutableArray का उपयोग करें।
शुद्ध कार्य है। ऐसा नहीं है, खरीदें कई फ्रेमवर्क एपीआई को शुद्ध फ़ंक्शन की तरह डिज़ाइन किया गया है। जैसे कार्यों को देखो CGRectMake()
या CGAffineTransformMake()
। स्पष्ट रूप से सूचक रूप अधिक कुशल दिखता है। हालांकि संकेत के साथ अप्रत्यक्ष तर्क पक्ष-प्रभाव-मुक्त की पेशकश नहीं कर सकता। यथासंभव विशुद्ध रूप से डिजाइन संरचनाएं। राज्य वस्तुओं को भी अलग करें। किसी वस्तु को मान देने के -copy
बजाय उपयोग करें -retain
। क्योंकि साझा स्थिति म्यूटेशन को अन्य ऑब्जेक्ट में चुपचाप मूल्य के लिए प्रभावित कर सकती है। तो साइड-इफ़ेक्ट-फ़्री नहीं हो सकता। यदि आपके पास बाहरी वस्तु से मूल्य है, तो इसे कॉपी करें। तो यह भी संभव के रूप में कम से कम साझा राज्य डिजाइन महत्वपूर्ण है।
हालांकि अशुद्ध कार्यों का भी उपयोग करने से डरो मत।
आलसी मूल्यांकन है। -[UIViewController view]
संपत्ति जैसा कुछ देखें । जब ऑब्जेक्ट बनाया जाएगा तो दृश्य नहीं बनाया जाएगा। यह तब बनाया जाएगा जब कॉलर view
पहली बार संपत्ति पढ़ रहा हो । UIImage
तब तक लोड नहीं किया जाएगा जब तक कि इसे वास्तव में खींचा न जाए। इस डिजाइन की तरह कई कार्यान्वयन हैं। संसाधन प्रबंधन के लिए इस तरह के डिजाइन बहुत सहायक होते हैं, लेकिन यदि आप आलसी मूल्यांकन की अवधारणा को नहीं जानते हैं, तो उनके व्यवहार को समझना आसान नहीं है।
बंद है। जितना हो सके सी-ब्लॉक्स का इस्तेमाल करें। यह आपके जीवन को बहुत सरल करेगा। लेकिन उपयोग करने से पहले ब्लॉक-मेमोरी-मैनेजमेंट के बारे में एक बार और पढ़ें।
सेमी-ऑटो जीसी है। NSAutoreleasePool। -autorelease
प्राथमिक का उपयोग करें । -retain/-release
जब आपको वास्तव में जरूरत हो, तो सेकेंडरी का उपयोग करें । (पूर्व: स्मृति अनुकूलन, स्पष्ट संसाधन विलोपन)
autorelease
कि आम तौर पर मेमोरी लंबे समय तक चलेगी , और मैनुअल retain/release
मामले में मेमोरी की खपत को कम कर सकता है। हालांकि यह विशेष केस ऑप्टिमाइज़ेशन के लिए मार्गदर्शन होना चाहिए (यहां तक कि आप हमेशा महसूस कर रहे हैं!), अभ्यास के रूप में समय से पहले अनुकूलन को सामान्य करने का कारण नहीं हो सकता है । और वास्तव में, आपका सुझाव मुझसे विपरीत नहीं है। मैंने इसे वास्तव में जरूरत के मामले के रूप में उल्लेख किया :)