2009-06-17 15 views
9

साथ उदाहरण चर का उपयोग करना मैं में Obj सी और कोको कई वर्षों का अनुभव है, लेकिन अभी यह में वापस हो रही है और Obj सी की अग्रिम 2.0 आदिआधुनिक क्रम

मैं पाने के लिए कोशिश कर रहा हूँ आधुनिक रनटाइम और घोषित गुणों के आस-पास मेरा सिर इत्यादि। एक चीज जो मुझे थोड़ा उलझन देती है वह आधुनिक रनटाइम की क्षमता है जो iVars को पूरी तरह से बनाया गया है। और निश्चित रूप से इसका तात्पर्य है कि आपके कोड में आपको हमेशा मूल्य का उपयोग करने के लिए self.property का उपयोग करना चाहिए।

हालांकि, init * और dealloc (मान लीजिए कि आप जीसी का उपयोग नहीं कर रहे हैं) विधियों में हमें सीधे iVar (वर्तमान रनटाइम में) का उपयोग करना चाहिए।

तो प्रश्न हैं:

  1. हम init * और आधुनिक रनटाइम साथ dealloc में संपत्ति accessors उपयोग करना चाहिए?

  2. यदि ऐसा है तो, क्यों इस प्रकार भिन्न है? क्या यह सिर्फ इसलिए है क्योंकि संकलक iVar नहीं देख सकता है?

  3. यदि मुझे किसी एक्सेसर को ओवरराइड करने की आवश्यकता है, तो क्या मैं अभी भी उस iVar तक पहुंच सकता हूं जिसे रनटाइम पर परिभाषित किया जाएगा या क्या मुझे एक वास्तविक iVar परिभाषित करना होगा कि रनटाइम तब उपयोग करेगा?

  4. फिर, मैं संश्लेषित इवर का उपयोग कर सकते हैं, कारण है कि मैं init * और dealloc तरीकों के लिए यह करने के लिए जारी नहीं रह सकता?

मैं डॉक्स कई बार पढ़ा है, लेकिन वे इस सब के बारे में थोड़ा अस्पष्ट लग रहा था और मुझे यकीन है कि मैं इसे क्रम तय करने के लिए कि कैसे मैं कोडिंग जारी रखना चाहते हैं में अच्छी तरह से समझ होना चाहता हूँ।

आशा है कि मेरे प्रश्न स्पष्ट हैं।


परीक्षण के त्वरित सारांश:

  1. आप विरासत में इवर घोषित नहीं करते, संकलक पूरी तरह से दुखी है

  2. आप विरासत संकलक में इवर आसपास #ifndef __OBJC2__ का उपयोग करते हैं खुश है और आप दोनों ivar को सीधे और संपत्ति के रूप में उपयोग कर सकते हैं

  3. इन आधुनिक क्रम, आप इवर तक पहुँचने के लिए सीधे बिना घोषणा इवर का संकलन

  4. @private घोषणा के दौरान त्रुटि देता है की कोशिश कर रहा इवर अपरिभाषित और संपत्ति

  5. आधुनिक क्रम में के रूप में उपयोग कर सकते छोड़ सकते हैं, जाहिर है, के लिए सीधी पहुँच की अनुमति देता है ivar, विरासत और आधुनिक दोनों

वास्तव में आगे जाने के लिए एक साफ तरीका नहीं देता है?

+3

जो लोग भ्रमित हो सकता है के लिए स्पष्ट करने के लिए, "आधुनिक रनटाइम" नए ऑब्जेक्टिव-सी क्रम को संदर्भित करता है कि हो सकता है * केवल * आईफोन ऐप्स और 64-बिट प्रक्रियाओं द्वारा 10.5 या उच्चतर पर उपयोग किया जाना चाहिए। कोई भी उद्देश्य-सी कोड जो 32-बिट या टाइगर या पहले "लीगेसी रनटाइम" के तहत चलता है। –

+0

http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html –

+0

@Quinn - मुझे नहीं पता था कि आईफोन ओएस आधुनिक रनटाइम का उपयोग करता है। वह बहुत प्यारा है। –

उत्तर

10

वर्तमान में (ओएस एक्स 10.5/जीसीसी 4.0.1) कंपाइलर में, आप सीधे रनटाइम-संश्लेषित ivars तक नहीं पहुंच सकते हैं। ग्रेग पार्कर, ओएस एक्स क्रम इंजीनियरों में से एक कोको-देव सूची पर this तरह से रख (12 मार्च, 2009):

आप कर सकते हैं वर्तमान संकलक में नहीं। भावी कंपाइलर को ठीक करना चाहिए। के दौरान स्पष्ट @ निजी Ivars का उपयोग करें। एक @private ivar को अनुबंध का हिस्सा नहीं माना जाना चाहिए - यह है कि @private का अर्थ है, संकलक चेतावनियों और लिंकर त्रुटियों द्वारा लागू किया गया है।

और का कोई तरीका क्यों नहीं है नए रनटाइम के लिए .m फ़ाइल में उदाहरण चर स्पष्ट रूप से घोषित करें?

तीन कारण हैं: (1) कुछ गैर तुच्छ डिज़ाइन विवरण बाहर काम करने के, (2) संकलक-इंजीनियर-घंटे सीमित हैं, और (3) @private ivars आम तौर पर काफी अच्छा कर रहे हैं।

तो, अभी आप, गुण का उपयोग करने के init और dealloc में भी बिंदु संकेतन का उपयोग करना चाहिए। यह इन मामलों में सीधे इवर का उपयोग करने के सर्वोत्तम अभ्यास के खिलाफ चला जाता है, लेकिन इसके आसपास कोई रास्ता नहीं है। मुझे लगता है कि रनटाइम-संश्लेषित इवर (और प्रदर्शन लाभ) का उपयोग करने में आसानी ज्यादातर मामलों में इससे अधिक है। जहां आपको सीधे ivar तक पहुंचने की आवश्यकता है, आप एक @private ivar का उपयोग कर सकते हैं क्योंकि ग्रेग पार्कर सुझाव देता है (ऐसा कुछ भी नहीं है जो आपको स्पष्ट रूप से घोषित और रनटाइम-संश्लेषित ivars मिश्रण से रोकता है)।

अद्यतन ओएस एक्स 10.6 के साथ, 64-बिट क्रम self->ivar के माध्यम से संश्लेषित ivars के लिए सीधी पहुँच की अनुमति नहीं है।

+0

धन्यवाद बैरी, मैंने यही सोचा और पुष्टि करने की उम्मीद कर रहा था। जैसा कि मैंने नीचे एक टिप्पणी में उल्लेख किया है, मैं वास्तव में उत्तर के रूप में चिह्नित करने से पहले यह एक परीक्षण देने जा रहा हूं। –

+0

ठीक है, मैंने अभी पुष्टि की है कि यह वास्तव में यहां वर्णित कार्य करता है। परिणामों के लिए ऊपर संपादित देखें। –

+0

ऐसा प्रतीत होता है कि आप "स्वयं->" भाग छोड़ सकते हैं और केवल ivar नाम का भी उपयोग कर सकते हैं। हालांकि यह वर्तमान में आईफोन रनटाइम के लिए काम नहीं कर रहा है। – briankc

0

इसी तरह की जानकारी के साथ another SO question है, लेकिन यह काफी डुप्लिकेट नहीं है।

कि क्रम पर निर्भर व्यवहार में हैं (यह भी देखें "रनटाइम मतभेद")::

लब्बोलुआब यह है, Objective-C 2.0 documentation से, और Mark Bessey's answer से उद्धृत इस प्रकार है विरासत रनटाइम के लिए, @terterface ब्लॉक में आवृत्ति चर पहले ही घोषित किया जाना चाहिए। यदि समान नाम और संगत प्रकार का एक उदाहरण चर मौजूद है, तो इसका उपयोग किया जाता है-अन्यथा, आपको एक कंपाइलर त्रुटि मिलती है।

आधुनिक रनटाइम के लिए, आवृत्ति चर आवश्यकतानुसार संश्लेषित होते हैं। यदि एक ही नाम का एक इंस्टेंस वैरिएबल पहले से मौजूद है, तो इसका उपयोग किया जाता है।

आप init* और dealloc तरीकों में संपत्ति accessors उपयोग नहीं करना चाहिए, एक ही कारण है कि आप उन्हें विरासत क्रम में उपयोग नहीं करना चाहिए के लिए:

मेरे समझ इस प्रकार है यह आप संभावित त्रुटियों के लिए खुला छोड़ देता है यदि आप बाद में संपत्ति विधियों को ओवरराइड करते हैं, और ऐसा कुछ ऐसा करते हैं जो init* या dealloc में नहीं किया जाना चाहिए।

आप दोनों इवर संश्लेषण करने और इस प्रकार संपत्ति तरीकों ओवरराइड करने के लिए सक्षम होना चाहिए:

@interface SomeClass 
{ 
} 
@property (assign) int someProperty; 
@end 

@implementation SomeClass 
@synthesize someProperty; // this will synthesize the ivar 
- (int)someProperty { NSLog(@"getter"); return someProperty; } 
- (void)setSomeProperty:(int)newValue 
{ 
    NSLog(@"setter"); 
    someProperty = newValue; 
} 
@end 

कौन सा मुझे सुराग को लगता है कि आप अपने init* और dealloc में संश्लेषित इवर उपयोग करने में सक्षम हो जाएगा विधियों के साथ-साथ। एकमात्र गोचाचा मैं सोच सकता था कि @synthesize लाइन से पहले init* और dealloc स्रोत फ़ाइल में विधियों की परिभाषाएं आ सकती है।

अंत में, इंटरफ़ेस में घोषित इवर अभी भी काम करते हैं, यह अभी भी आपकी सबसे सुरक्षित शर्त है।

+0

हम्म, यह टिप्पणी इस बात का खंडन करती है कि बैरी ने ग्रेग पार्कर को उद्धृत करने में क्या उल्लेख किया है और सहजता से गलत लगता है (हालांकि अंतर्ज्ञान कभी-कभी बकवास हो सकता है :-))। ऐसा लगता है कि निजी आईवर घोषणा जाने का रास्ता होगा। –

+0

उनके उत्तर के आधार पर, बैरी वार्क के पास इस मामले में मुझसे अधिक अनुभव है। मैं अपने अंतर्ज्ञान पर भरोसा करता हूं:) –

1

उदाहरण चर के बाद से खुद को केवल आधुनिक क्रम में संश्लेषित किया जा सकता है (और 32-बिट या पूर्व तेंदुए के तहत @interface में घोषित किया जाना चाहिए), यह सबसे सुरक्षित है/सबसे भी इवर

घोषित करने के लिए पोर्टेबल
  • क्या हमें आधुनिक रनटाइम के साथ init * और dealloc में संपत्ति एक्सेसर्स का उपयोग करना चाहिए?

अंगूठे का मेरा नियम "संभवतः" -init* के लिए -dealloc के लिए "नहीं आम तौर पर" है, और।

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

किसी ऑब्जेक्ट को हटाने पर, आप किसी भी ivar ऑब्जेक्ट्स को रिलीज़ करना चाहते हैं, लेकिन नए स्टोर नहीं करना चाहते हैं। ऐसा करने का एक आसान तरीका संपत्ति को शून्य (myObject.myIvar = nil) पर सेट करना है, जो मूल रूप से [myObject setMyIvar:nil] पर कॉल करता है। चूंकि संदेशों को शून्य से अनदेखा किया जाता है, इसमें कोई खतरा नहीं है। हालांकि, यह अधिक है जब [myIvar रिलीज]; आम तौर पर आपको केवल इतना ही चाहिए।आम तौर पर, उन परिस्थितियों में संपत्ति (या सीधे, सेटर) का उपयोग न करें जहां परिवर्तनीयता को सेट करने से अलग-अलग व्यवहार करना चाहिए।

मैं इनट/डेलोक में संपत्ति एक्सेसर्स का उपयोग करने के खिलाफ ईजेम्स के तर्क को समझ सकता हूं, लेकिन फ्लिपसाइड यह है कि यदि आप संपत्ति व्यवहार बदलते हैं (उदाहरण के लिए, प्रतिलिपि बनाए रखने से बदलें, या केवल बनाए रखने के बिना असाइन करें) और डॉन इसे init में उपयोग नहीं करते हैं, या इसके विपरीत, व्यवहार भी सिंक से बाहर हो सकता है। यदि ivar को प्रारंभ करना और संशोधित करना एक ही कार्य करना चाहिए, तो दोनों के लिए संपत्ति एक्सेसर का उपयोग करें।

  • यदि हां, तो यह अलग क्यों है? क्या यह सिर्फ इसलिए है क्योंकि संकलक ivar नहीं देख सकता है?

वर्ग के आकार और लेआउट अधिक समझदारी से है, जिसके कारण आप उपवर्गों पुनः संकलित किए बिना ivars के लेआउट बदल सकते हैं के साथ आधुनिक क्रम से संबंधित है। यह नाम और प्रकार से संबंधित ivar के नाम और प्रकार का अनुमान लगाने में भी सक्षम है। Objective-C 2.0 Runtime Programming Guide में अधिक जानकारी है, लेकिन फिर से, मुझे नहीं पता कि विवरण कितनी गहराई से समझाया गया है।

  • मैं एक्सेसर ओवरराइड करने के लिए की जरूरत है, मैं अभी भी है कि इवर जो रनटाइम पर परिभाषित किया जाएगा या मैं एक वास्तविक इवर कि क्रम तो उपयोग करेगा परिभाषित करने के लिए है का उपयोग कर सकते हैं?

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

  • फिर, अगर मैं संश्लेषित इवर उपयोग कर सकते हैं, मैं क्यों init * और dealloc तरीकों के लिए यह करने के लिए जारी नहीं रह सकता?

आप संपत्ति का उपयोग और/या किसी भी समय इवर के बाद उदाहरण आबंटित किया गया है करने के लिए सक्षम होना चाहिए।

+0

दुर्भाग्यवश दस्तावेज़ इस में बहुत गहरा नहीं जाते हैं। यहां प्रश्नों का यही कारण था। आप iVars के बारे में बता रहे हैं "बनाने के लिए" हालांकि भ्रामक है। आधुनिक रनटाइम क्लास स्ट्रक्चर को लेआउट का कारण ले सकता है क्योंकि यह रनटाइम पर करता है। इसलिए ये चर अभी तक मौजूद नहीं हैं। हालांकि, मुझे लगता है कि मैं 64-बिट ऐप में कुछ परीक्षण चलाऊंगा और रिपोर्ट करूंगा। –

0

मैं एक ही समस्या में भाग रहा हूं।

सार्वजनिक हैडर

@interface MyObject:NSObject { 
} 
@property (retain) id instanceVar; 
@property (retain) id customizedVar; 
@end 

निजी हैडर/कार्यान्वयन

@interface MyObject() 
@property (retain) id storedCustomizedVar; 
@end 

@implementation MyObject 
@synthesize instanceVar, storedCustomizedVar; 
@dynamic customizedVar; 

- customizedVar { 
    if(!self.storedCustomizedVar) { 
    id newCustomizedVar; 
    //... do something 
    self.storedCustomizedVar= newCustomizedVar; 
    } 
    return self.storedCustomizedVar; 
} 

- (void) setCustomizedVar:aVar { 
    self.storedCustomizedVar=aVar; 
} 

@end 

यह इतना सुंदर नहीं है, कम से लेकिन: जिस तरह से मैं चारों ओर संश्लेषित उदाहरण चर उपयोग करने में सक्षम नहीं किया जा रहा काम कर रहा हूँ पीछा कर रहा है कम से कम यह मेरी सार्वजनिक हेडर फ़ाइल को साफ रखता है।

यदि आप केवीओ का उपयोग करते हैं तो आपको कस्टमाइज्ड वार को संग्रहीत कस्टमाइज्ड वार की निर्भर कुंजी के रूप में परिभाषित करने की आवश्यकता है।

0

मैं अपेक्षाकृत नया ओबीजे-सी (लेकिन प्रोग्रामिंग नहीं) के लिए नया हूं और इस विषय से भी उलझन में हूं।

पहलू जो मुझे चिंतित करता है वह यह है कि यह अनजाने में संपत्ति के बजाय iVar का उपयोग करना अपेक्षाकृत आसान लगता है। उदाहरण के लिए लेखन:

myProp = someObject;

के बजाय

self.myProp = someObject;

मान्य है कि यह "उपयोगकर्ता" त्रुटि है, लेकिन यह अभी भी कुछ कोड में गलती से करना आसान लगता है, और एक बनाए रखा या परमाणु संपत्ति के लिए यह संभावित रूप से समस्याओं का कारण बन सकता है।

आदर्श रूप से मैं कोई iVar उत्पन्न करते समय संपत्ति के नाम पर कुछ पैटर्न लागू करने के लिए रनटाइम प्राप्त करने में सक्षम होना पसंद करूंगा। जैसे हमेशा उन्हें "_" के साथ उपसर्ग करें।

इस समय अभ्यास में मैं मैन्युअल रूप से ऐसा कर रहा हूं - स्पष्ट रूप से मेरे इवर घोषित करता हूं, और जानबूझकर उन्हें गुणों से अलग नाम देता हूं। मैं एक पुरानी शैली 'एम' उपसर्ग का उपयोग करता हूं, इसलिए यदि मेरी संपत्ति "मायप्रॉप" है, तो मेरा आईवर "एमएमप्रॉप" होगा। फिर मैं दो को जोड़ने के लिए @Synthesize myProp = mmyProp का उपयोग करता हूं।

यह थोड़ा सा गड़बड़ है, और थोड़ा अतिरिक्त टाइपिंग है, लेकिन यह मेरे लिए लायक है कि कोड में थोड़ा और स्पष्ट रूप से असंतोष करने में सक्षम हो। निस्संदेह मैं इसे अभी भी गलत समझ सकता हूं और mmyProp = someObject टाइप कर सकता हूं, लेकिन मुझे आशा है कि 'एम' उपसर्ग मुझे मेरी त्रुटि के बारे में सूचित करेगा।

यह बहुत अच्छा लगेगा अगर मैं संपत्ति घोषित कर सकता हूं और संकलक/रनटाइम बाकी कर सकता हूं, लेकिन जब मेरे पास बहुत सारे कोड हैं तो मेरा आंत वृत्ति मुझे बताती है कि अगर मैं अभी भी गलती करूंगा init/dealloc के लिए मैन्युअल नियमों का पालन करने के लिए।

बेशक वहाँ भी अन्य बातों के मैं भी गलत क्या कर सकते हैं के बहुत सारे हैं ...

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