2009-04-02 9 views
7

मैं अभी शुरू कर रहा हूं (पिछले कुछ दिनों के लिए बहुत कुछ पढ़ रहा हूं)। यहां कुछ प्रश्न दिए गए हैं जिन्हें मैंने ढेर किया है, उम्मीद है कि कोई उन्हें जवाब दे सकता है।कुछ शुरुआती उद्देश्य-सी/आईफोन प्रश्न

1. (स्वयं! = शून्य) प्रारंभकर्ता कोड में जांचें। क्यो ऐसा करें? कुछ "रन-केवल-एक बार" कोड में आकस्मिक पहुंच को रोकने के लिए जो वहां लपेटा गया है? यह आकस्मिक पहुंच कहां से आ सकती है? इस तरह के चेक करने से पता चलता है कि मेरे पास क्या हो रहा है पर नियंत्रण नहीं है।

 
- (id)init { 
    self = [super init] 
    if (self != nil) { 
    // Code.. 
    } 
    return self; 
} 

2. कैसे यह आप कुछ भी है कि स्थिर तरीकों लौटने को मुक्त करने की जरूरत नहीं है? (या यह वह विचार है जो मुझे मिला है)

3. str = @ "हाय वहाँ है!" से

str = [[NSString alloc] initWithString:@"Hi there!"];

अलग रूप में मैं समझता हूँ, आप पहली बार साथ दूसरी विधि के साथ प्राप्त में str जारी करने के लिए है, लेकिन नहीं? यदि हां, तो पहला कब जारी किया जाता है? कौन सा बेहतर है (टाइपिंग लम्बाई पर ध्यान नहीं दे रहा है)?

4. आईफोन में कोई कचरा संग्रह नहीं है, तो ऑटोरेलीज क्या है? मैंने मुख्य रूप से "एक ऑटोरेलीज पूल" नामक कुछ देखा है। [MyObject autorelease] है; myObject को निकटतम रैपिंग "ऑटोरेलीज पूल" में जोड़ने का एक तरीका, जो इसे जारी करेगा? असल में, कुछ जादू इसे खुद को मुक्त करने से बचने के लिए? इसका इस्तेमाल क्यों करें?

ठीक है, अब यह है। किसी भी उत्तर के लिए धन्यवाद!

उत्तर

11
  1. में ऑब्जेक्टिव-सी है, यह -init से स्वयं के अलावा अन्य एक उदाहरण वापस जाने के लिए संभव है। कक्षाएं ऐसा करती हैं, उदाहरण के लिए, सिंगलटन इंस्टेंस को लागू करने के लिए, या क्लास क्लस्टर के मामले में। NSNumber, उदाहरण के लिए, अपने प्रारंभकर्ता को पास किए गए मान के प्रकार के आधार पर उप-वर्ग लौटाता है। तो जब आप [[NSNumber alloc] initWithLong:long_value] पर कॉल करते हैं, NSNumber के -initWithLong: प्रारंभकर्ता को NSNumber के +alloc के बाद बुलाया जाता है, लेकिन NSNumber का उप-वर्ग ऑरिंगियल कॉलर पर वापस किया जा सकता है।इस प्रकार पैटर्न

    स्वयं = [सुपर इनिट];

    जो को [super init] के मान पर पुन: असाइन करता है ताकि वास्तविक उदाहरण के लिए self अंक लौटा सकें। यदि +alloc या सुपर की init विधि विफल हो जाती है, तो [super init] का परिणाम nil हो सकता है। बचने के लिए, एक असफल आरंभीकरण के मामले में साइड इफेक्ट, पैटर्न तो हो जाता है

    - (id) init { 
        if(self = [super init]) { 
        // do initialization of instance variables etc. 
        } 
    
        return self; 
    } 
    

    ध्यान दें कि आप init विधि से self (या nil या एक अन्य उदाहरण) लौट जाना चाहिए। आप [super init] पर स्वयं को असाइन करना चाहिए और आप अधिक काम करने से पहले nil की जांच कर सकते हैं।

  2. आपको एक स्टेक विधि का रिटर्न वैल्यू जारी करना पड़ सकता है। आपको कोको मेमोरी मैनेजमेंट guide पढ़ना चाहिए। नियम आम तौर पर काफी सरल होता है: यदि आपके द्वारा कॉल की जाने वाली विधि में "हस्ताक्षर", "आवंटन" या "प्रतिलिपि" है, तो परिणाम कॉलर से संबंधित है और कॉलर को उस उदाहरण पर -release पर कॉल करना होगा या एक स्मृति होगी रिसाव। बेशक आपको किसी अन्य चीज़ पर -retain पर कॉल करना चाहिए (यानी "एलोक", "नई" या "कॉपी" विधि से नहीं) आप उस संदर्भ के साथ -release या -autorelease पर कॉल करना चाहते हैं और फिर कॉल करना चाहते हैं।

  3. str = @"Hi there!", str संभालने NSString *str; के रूप में घोषित किया गया था स्ट्रिंग निरंतर @"Hi there!" to the value of the str variable. You do not need to retain or release string constants. str = का पता प्रदान करती है [[NSString alloc] initWithString: @ "नमस्कार!"]; allocates a new string instance. The value of str will be the address of this instance. Each call of str = [[NSString alloc] initWithString: @ "हाय वहाँ!"]; again will allocate a new instance. So after str2 = [[एनएसएसटींग आवंट] initWithString: @ "हाय वहाँ!"]; , str! = Str2 , while after str2 = @ "हाय वहाँ!", str==str2this उत्तर भी देखें।

  4. -autorelease रिसीवर को वर्तमान NSAutoreleasPool पर जोड़ता है। जब पूल निकाला जाता है (आमतौर पर वर्तमान रन लूप पुनरावृत्ति के अंत में, या जब पूल मैन्युअल रूप से निकाला जाता है), पूल पूल के सभी उदाहरणों पर -release पर कॉल करता है। यदि यह -release 0 को बरकरार रखने के लिए 0 को छोड़ देता है, तो ऑब्जेक्ट को हटा दिया जाता है (और -dealloc कहा जाता है) जैसा कि किसी अन्य -release के साथ होता है। एक ऑटोरेलीज पूल का उपयोग आम तौर पर आईफोन पर फहराया जाता है क्योंकि यह पूल लूप पुनरावृत्ति के अंत में इसे निकालने से पहले पूल में कई अप्रयुक्त उदाहरण जमा कर सकता है। यदि आप -autorelease के बजाय -release का उपयोग कर सकते हैं, तो आपको आम तौर पर चाहिए। फिर, अधिक जानकारी के लिए कोको स्मृति प्रबंधन guide देखें।

+0

शानदार जवाब! –

+0

इस तरह के एक अच्छी तरह से बाहर, उदाहरण के जवाब से भरा। धन्यवाद, इसमें से अधिकांश अब स्पष्ट है। स्वीकार किए जाते हैं। – Karolis

1

1: यह जांच यह सुनिश्चित करने के लिए है कि सुपर कन्स्ट्रक्टर ने एक नई वस्तु वापस कर दी हो।

2: स्टेटिक तरीकों एक उदाहरण

3 का उल्लेख नहीं है: "हाय"

str = @"Hi there!"

यह लगातार तार का पता प्रदान करती है सूचक str को

str = [[NSString alloc] initWithString:@"Hi there!"];

यह एक स्ट्रिंग और प्रतियां आवंटित "हाय वहाँ!" इसके लिए इसका मतलब है कि ए) str संशोधित है और बी) जब आप इसके साथ काम करते हैं तो इसे हटा दिया जाना चाहिए।

+0

लेकिन सामान्य रूप से, दोनों str उपयोग स्मृति की समान मात्रा का उपभोग करेंगे, केवल पहला अपरिवर्तनीय है। दूसरी विधि गारंटी का उपयोग नहीं करता है जब भी मुझे इसकी आवश्यकता होती है तो अंतरिक्ष मुक्त हो जाता है? बस असाइनिंग @ "हाय वहाँ!" अंतरिक्ष भी लेता है, नहीं? लेकिन स्मृति में उस जगह पर कोई नियंत्रण नहीं है, है ना? – Karolis

+0

एनएसएसटींग अपरिवर्तनीय है, इसलिए किसी भी उदाहरण में str संशोधित नहीं है। –

+0

नहीं, str एक अपरिवर्तनीय स्ट्रिंग के लिए एक परिवर्तनीय कंटेनर है। –

1

self = [super init]; 

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

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

आप आवश्यकतानुसार अपने स्वयं के ऑटोरेलीज पूल बना सकते हैं।

str = [[NSString alloc] initWithString:@"Hi there!"]; 

यह पंक्ति एक स्ट्रिंग बनाता है जो एक ऑटोरेलीज पूल में नहीं है, इसलिए आपको इसे मैन्युअल रूप से रिलीज़ करना होगा। बस

@"Hi there!"; 

एक स्ट्रिंग देता है जिसे आपको रिलीज़ करने की चिंता करने की आवश्यकता नहीं है। अपने पिछले उदाहरण को विस्तारित करना:

str = [[[NSString alloc] initWithString:@"Hi there!"] autorelease]; 

एक स्ट्रिंग बनाने का एक और तरीका होगा जिसे आपको रिलीज़ करने की चिंता करने की आवश्यकता नहीं है।

कचरा संग्रह और ऑटोरेलीज पूल के बीच एक अंतर यह है कि कचरा संग्रह परिपत्र संदर्भों के साथ काम करता है। ऑटोरेलीज पूल का उपयोग करके, आप दो वस्तुओं को नहीं रखना चाहते हैं जो एक-दूसरे को बनाए रखें और उम्मीद करें कि एक बार उन्हें और कुछ भी संदर्भित नहीं किया जाता है, वे अस्तित्व से बाहर निकल जाएंगे; वे नहीं करेंगे

+0

तो ऑटोरेलीज पूल में ऑब्जेक्ट्स डालने का लाभ उन्हें मैन्युअल रूप से रिलीज़ नहीं करना है, लेकिन जब इसे रिलीज़ करने के लिए * * पर नियंत्रण खो रहा है? असल में, अगर मैं अपना ऑब्जेक्ट ऑटोरेलीज पूल को देता हूं, तो जब भी ऐसा होता है तो इसे जारी करने के लिए मैं करुणा पर हूं? – Karolis

+0

जब आप इसे रिलीज़ करते हैं तो आप नियंत्रण खो सकते हैं, लेकिन जब इसे हटाया नहीं जाता है। यदि आप ऑटोरिलीज पूल में रखे गए किसी ऑब्जेक्ट को रखना चाहते हैं, तो आप बस [obj retain] को कॉल कर सकते हैं ताकि ऑटोरलीज पूल रिलीज़ होने के बाद इसकी बरकरार संख्या 1 से भी बड़ी हो। –

1
  1. तो स्वयंशून्य है सुपर initialisation के बाद तो आप स्मृति से बाहर शायद कर रहे हैं। कार्रवाई का आपका एकमात्र उचित तरीका शून्य वापस करना है और उम्मीद है कि चीजें ढेर को आगे बढ़ाएंगी।

  2. ढेर पर आवंटित करने की अनुमति नहीं है, इसलिए मुफ्त में कुछ भी नहीं है।

  3. पहले उदाहरण में, स्ट्रिंग को आपके ऐप के डेटा सेगमेंट में संकलित किया गया है और इसे मुक्त नहीं किया जा सकता है। दूसरे उदाहरण में, आप ढेर से स्मृति आवंटित कर रहे हैं और अपनी स्थिर स्ट्रिंग (डेटा सेगमेंट से) को कॉपी कर रहे हैं।

  4. यह आसान कचरा संग्रह है। इसका उपयोग क्यों करें, सरल जवाब नहीं है। सीमित संसाधनों के कारण आईफोन पर ऑटोरेलीज का उपयोग करने की अनुशंसा नहीं की जाती है।

+0

तो मूल रूप से, str = @ "हाय वहाँ!" पूरे ऐप रनटाइम के लिए इस डेटा सेगमेंट में बैठता है, भले ही कोडिंग भाग को गीला करने के बिना कोडिंग किया गया हो या नहीं? दूसरे शब्दों में, मेरे पास जितने अधिक स्ट्रिंग हैं, उतनी अधिक मेमोरी मेरे ऐप को प्रारंभ में आवश्यकता होगी? धन्यवाद – Karolis

+0

"हाय वहाँ!" बीएसएस अनुभाग में बैठता है, स्ट्र (यानी, 4-8 बाइट्स के लिए भंडारण एक पते का प्रतिनिधित्व करने के लिए लेता है) डेटा खंड में बैठता है। बीएसएस अनुभाग में स्ट्रिंग के पते के साथ str प्रारंभ किया गया है। –

2
  1. सोचा था की एक स्कूल है कि ज्यादातर मामलों में, self सूचक का आवंटन कुछ है कि प्रणाली को क्या करना चाहिए, और नहीं प्रोग्रामर है नहीं है।

इसके अलावा, कई लोग कार्यक्रम प्रवाह की मुख्य पंक्ति को जितना संभव हो उतना अनियमित मानना ​​पसंद करते हैं। जो मामले में initialisation कोड को फिर से लिखा जा सकता है के रूप में:

- (id)init { 
    if (![super init]) { 
     return nil; // There is a problem so bail early. 
    } 
    // Initialisation code here. 
    return self 
} 

Will Shipley इतना से मुझे क्या करना बेहतर बताते हैं।

+0

धन्यवाद, वह ब्लॉग पोस्ट बहुत उपयोगी था। और भ्रमित। मैं समझता हूं कि यह कोको के बारे में बात करता है, कोको टच नहीं, तो हो सकता है कि यह जांच अभी भी आईफोन पर्यावरण (स्मृति परिस्थितियों में से) में दूसरों द्वारा उल्लिखित कारणों के लिए मान्य है? – Karolis

+0

यदि आप अभी शुरू कर रहे हैं, तो यह भ्रमित हो सकता है। मैंने इसे एक उदाहरण के रूप में लाया कि शुरुआती चीजों को शुरुआती चीजों को लिखने के अन्य तरीके भी हैं। विल्स के "पिंप माई कोड" श्रृंखला को बुकमार्क करें और कुछ महीनों के बाद इसे वापस जाएं; आपको कोको/ओब्जे-सी कोड लिखने के बारे में सोचने के लिए उपयोगी लगेगा। – Abizern

+0

उद्देश्य-सी भाषा है। कोको और कोको टच ढांचे हैं। हालांकि कुछ पैटर्न दोनों के बीच भिन्न होते हैं, उद्देश्य-सी (इनिट पैटर्न सहित) दोनों के सिद्धांत दोनों पर लागू होते हैं। –

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