@implementationब्लॉक में या एक वर्ग विस्तार में उदाहरण चर डालने की क्षमता , "आधुनिक उद्देश्य-सी रनटाइम" की एक विशेषता है, जिसका उपयोग आईओएस के प्रत्येक संस्करण और 64-बिट मैक ओएस एक्स कार्यक्रमों द्वारा किया जाता है।
यदि आप 32-बिट मैक ओएस एक्स एप्लिकेशन लिखना चाहते हैं, तो आपको अपने उदाहरण चर को @interfaceघोषणा में रखना होगा । संभावना है कि आपको अपने ऐप के 32-बिट संस्करण का समर्थन करने की आवश्यकता नहीं है, हालांकि। ओएस एक्स ने संस्करण 10.5 (तेंदुए) के बाद से 64-बिट ऐप्स का समर्थन किया है, जो पांच साल पहले जारी किया गया था।
तो, चलिए मान लेते हैं कि आप केवल ऐसे ऐप्स लिख रहे हैं जो आधुनिक रनटाइम का उपयोग करेंगे। आपको अपने ivars कहां रखना चाहिए?
विकल्प 0: में @interface(यह मत करो)
सबसे पहले, आइए हम एक घोषणा में उदाहरण चर क्यों नहीं डालना चाहते हैं @interface।
@interfaceकक्षा के उपयोगकर्ताओं को क्रियान्वयन के विवरणों में उदाहरण चर डालते हुए । कार्यान्वयन के विवरणों पर भरोसा करने के लिए यह उन उपयोगकर्ताओं (यहां तक कि अपनी कक्षाओं का उपयोग करते समय भी!) का नेतृत्व कर सकता है जो उन्हें नहीं करना चाहिए। (यह इस बात से स्वतंत्र है कि क्या हम ivars घोषित करते हैं @private।)
एक @interfaceसंकलन में उदाहरण के चर को अधिक समय लगता है, क्योंकि किसी भी समय हम एक आइवर घोषणा को जोड़ते हैं, बदलते हैं या हटाते हैं, हमें .mइंटरफ़ेस आयात करने वाली प्रत्येक फ़ाइल को फिर से जोड़ना होगा ।
इसलिए हम उदाहरण चर नहीं रखना चाहते हैं @interface। हमें उन्हें कहां रखना चाहिए?
विकल्प 2: @implementationबिना ब्रेसिज़ में (यह मत करो)
इसके बाद, अपने विकल्प 2 पर चर्चा करें, "घुंघराले ब्रेस के ब्लॉक के बिना @ आइवर्स लागू करें"। यह उदाहरण चर घोषित नहीं करता है ! आप इस बारे में बात कर रहे हैं:
@implementation Person
int age;
NSString *name;
...
यह कोड दो वैश्विक चर को परिभाषित करता है। यह किसी भी उदाहरण चर घोषित नहीं करता है।
उदाहरण के लिए, यदि आपके पास वैश्विक चर की जरूरत है, तो यह आपकी .mफ़ाइल में वैश्विक चर को परिभाषित करने के लिए भी ठीक है @implementation, क्योंकि आप चाहते हैं कि आपके सभी उदाहरण कुछ राज्य को साझा करें, जैसे कि कैश। लेकिन आप इस विकल्प का उपयोग ivars घोषित करने के लिए नहीं कर सकते, क्योंकि यह ivars घोषित नहीं करता है। (इसके अलावा, आपके कार्यान्वयन के लिए निजी वैश्विक चर आमतौर पर staticवैश्विक नाम स्थान को प्रदूषित करने और लिंक-टाइम त्रुटियों को जोखिम में डालने से बचने के लिए घोषित किया जाना चाहिए ।)
यह आपके विकल्प 1 और 3 को छोड़ देता है।
विकल्प 1: @implementationब्रेसिज़ के साथ (इसे करें)
आमतौर पर हम विकल्प 1 का उपयोग करना चाहते हैं: उन्हें अपने मुख्य @implementationब्लॉक में, ब्रेसिज़ में रखें, जैसे:
@implementation Person {
int age;
NSString *name;
}
हमने उन्हें यहां रखा क्योंकि यह उनके अस्तित्व को निजी रखता है, मैंने पहले बताई गई समस्याओं को रोका, और क्योंकि आमतौर पर उन्हें कक्षा विस्तार में रखने का कोई कारण नहीं है।
तो जब हम आपके विकल्प 3 का उपयोग करना चाहते हैं, तो उन्हें क्लास एक्सटेंशन में डाल दें?
विकल्प 3: एक क्लास एक्सटेंशन में (केवल आवश्यक होने पर ही करें)
क्लास के एक्सटेंशन में उन्हें क्लास एक्सटेंशन में रखने का लगभग कोई कारण नहीं है @implementation। हम @implementationउस मामले में भी उन्हें डाल सकते हैं ।
लेकिन कभी-कभार हम एक ऐसा वर्ग लिख सकते हैं जो इतना बड़ा हो कि हम उसके स्रोत कोड को कई फाइलों में बाँटना चाहें। हम श्रेणियों का उपयोग करके ऐसा कर सकते हैं। उदाहरण के लिए, यदि हम लागू कर रहे थे UICollectionView(बल्कि एक बड़ा वर्ग), तो हम यह तय कर सकते हैं कि हम एक अलग स्रोत फ़ाइल में पुन: प्रयोज्य विचारों (कोशिकाओं और पूरक विचारों) की कतार का प्रबंधन करने वाले कोड को डालना चाहते हैं। हम उन संदेशों को एक श्रेणी में अलग करके ऐसा कर सकते हैं:
@interface UICollectionView : UIScrollView
- (id)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
@property (nonatomic, retain) UICollectionView *collectionViewLayout;
@end
@interface UICollectionView (ReusableViews)
- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier;
- (void)registerClass:(Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(UINib *)nib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)identifier;
- (id)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath;
- (id)dequeueReusableSupplementaryViewOfKind:(NSString*)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath;
@end
ठीक है, अब हम मुख्य UICollectionViewतरीकों UICollectionView.mको लागू कर सकते हैं और हम उन तरीकों को लागू कर सकते हैं जो पुन: प्रयोज्य विचारों को प्रबंधित करते हैं UICollectionView+ReusableViews.m, जो हमारे स्रोत कोड को थोड़ा अधिक प्रबंधनीय बनाता है।
लेकिन हमारे पुन: प्रयोज्य दृश्य प्रबंधन कोड को कुछ उदाहरण चर की आवश्यकता होती है। उन चरों को मुख्य वर्ग @implementationमें उजागर किया जाना है UICollectionView.m, इसलिए संकलक उन्हें .oफ़ाइल में उत्सर्जित करेगा । और हमें कोड में उन उदाहरण चर को उजागर करने की भी आवश्यकता है UICollectionView+ReusableViews.m, इसलिए वे विधियां आइवर का उपयोग कर सकती हैं।
यह वह जगह है जहाँ हमें एक वर्ग विस्तार की आवश्यकता है। हम एक निजी हेडर फ़ाइल में एक वर्ग विस्तार में पुन: प्रयोज्य-दृश्य-प्रबंधन ivars डाल सकते हैं:
@interface UICollectionView () {
NSMutableDictionary *registeredCellSources;
NSMutableDictionary *spareCellsByIdentifier;
NSMutableDictionary *registeredSupplementaryViewSources;
NSMutableDictionary *spareSupplementaryViewsByIdentifier;
}
- (void)initReusableViewSupport;
@end
हम इस हेडर फ़ाइल को अपने लाइब्रेरी के उपयोगकर्ताओं के लिए शिप नहीं करेंगे। हम इसे केवल इन UICollectionView.mऔर इंपोर्ट करेंगे UICollectionView+ReusableViews.m, ताकि इन आइवर को देखने की जरूरत की हर चीज इन्हें देख सके। हमने एक विधि में भी फेंक दिया है जिसे हम initपुन: प्रयोज्य-दृश्य-प्रबंधन कोड को प्रारंभ करने के लिए कॉल करने के लिए मुख्य विधि चाहते हैं । हम उस विधि को -[UICollectionView initWithFrame:collectionViewLayout:]अंदर से कॉल करेंगे UICollectionView.m, और हम इसे लागू करेंगे UICollectionView+ReusableViews.m।