2013-02-13 22 views
19

मैं एक tableview class बनाने के दौरान एक गलती की है, और गलती से रखा मेरी @property रूप copy जब मैं इसे परिभाषित:एक (प्रतिलिपि, nonatomic) एनएसएमयूटेबलएरे संपत्ति क्यों एनएसएआरआरएआर बनाती है?

@property (copy, nonatomic) NSMutableArray *words; 

मैं सरणी "सही ढंग से" initialised: (ध्यान दें कि यह तीसरे प्रयास है, इसलिए अनदेखा करें

+०१२३५१६४१०: तथ्य यह है कि मैं mutableCopy और ऐसा करने का अन्य बेहतर तरीके)

NSArray *fixedWords = @[@"Eeny", @"Meeny", @"Miny", @"Moe", @"Catch", @"A", @"Tiger", @"By", @"His", @"Toe"]; 
NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; 
self.words = mutWords; 

हालांकि का उपयोग नहीं कर रहा हूँ जब मैं बाद में सरणी को पुन: व्यवस्थित करने के लिए आया था, यह removeObjectAtIndex लाइन पर दुर्घटनाग्रस्त हो गया

id object = [self.words objectAtIndex:fromIndexPath.row]; 
NSUInteger from = fromIndexPath.row; 
NSUInteger to = toIndexPath.row; 
[self.words removeObjectAtIndex:from]; 
त्रुटि संदेश

unrecognized selector sent to instance 

साथ

यह पता लगाने की है कि यह खुदाई का एक बहुत लिया क्योंकि प्रतिलिपि मतलब यह है कि एक मानक (nonmutable) NSArray के निर्माण में NSMutableArray परिणाम बताए। क्या कोई समझा सकता है कि यह सही व्यवहार क्यों है?

+1

'@property (प्रतिलिपि, nonatomic) एनएसएमयूटेबलएरे * शब्द; 'प्रतिलिपि का कोई उपयोग नहीं, आप बनाए रखने के उपयोग shuld। –

+0

या –

+1

के संभावित डुप्लिकेट को बनाए रखने के बजाय मजबूत [उपयोग करने योग्य कॉपीविथज़ोन: कस्टम क्लास पर इसे अपरिवर्तनीय बनाता है] (http://stackoverflow.com/questions/14841130/using-mutablecopywithzone-on-custom-class-makes-it-immutable) –

उत्तर

31

-कोपी, जैसा कि उत्परिवर्तनीय कोको कक्षाओं द्वारा लागू किया गया है, हमेशा returns their immutable counterparts। इस प्रकार, जब एक एनएसएमयूटेबलएरे भेजा जाता है -कोपी, यह एक ही ऑब्जेक्ट युक्त एनएसएआरआरए देता है।

क्योंकि words स्मृति क्वालीफायर copy है, इस लाइन:

NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; 
self.words = mutWords; 

बाहर तक विस्तृत होता:

NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; 
self.words = [mutWords copy]; 

देखते हुए कि NSMutableArray NSArray का एक उपवर्ग है, संकलक शिकायत नहीं है, और अब आपके हाथों पर एक टिकिंग टाइम बम है क्योंकि एनएसएआरएआरई इसकी म्यूटेबल सबक्लास 'विधियों को नहीं पहचानता है (क्योंकि यह इसकी सामग्री को म्यूट नहीं कर सकता है)।

+4

स्पष्ट होने के लिए: 'प्रतिलिपि' सेटर पर संश्लेषित कार्यान्वयन में होती है, कॉल साइट पर नहीं। – bbum

+0

बस बीबीएम के बिंदु को बेहतर ढंग से चित्रित करने के लिए मेरे उत्तर में संशोधन किया। – macserv

+1

@bbum बेशक। यह सिर्फ अल्पसंख्यक के लिए था। मैं वास्तव में इस तरह के प्रश्न के लिए वास्तव में कौन से गुणों में शामिल नहीं होना चाहता था :) – CodaFi

7

गुण जादुई नहीं हैं, वे सिर्फ लघुरूप हैं। आपके ऑब्जेक्ट पर @property घोषित करने के लिए कंपाइलर को बैकिंग इंस्टेंस वेरिएबल और इसके लिए एक्सेसर विधियां बनाने के लिए कहा गया है। वास्तविक जेनरेट कोड आपके प्रॉपर्टी पर सेट की गई विशेषताओं पर निर्भर करता है।

यह याद रखना महत्वपूर्ण है कि डॉट सिंटैक्स का उपयोग करके संपत्ति सेट करना भी कम है। जब आप फोन ...

self.words = mutWords; 

... आप वास्तव में एक्सेसर उत्पन्न विधि पर्दे के पीछे, इस तरह लागू कर रहे हैं:

[self setWords:mutWords]; 

जब से तुम अपनी संपत्ति पर copy विशेषता निर्दिष्ट, आपको बता दिया संकलक कि कुछ इस तरह दिखता कोड के साथ कि -setWords: एक्सेसर विधि उत्पन्न करने के लिए:

- (void)setWords:(NSMutableArray *)words 
{ 
    _words = [words copy]; 
} 

सब जानने के बाद, आप देख सकते हैं happeni है एनजी: जेनरेटेड सेटर विधि इनपुट तर्क पर -copy पर कॉल करेगी, और परिणाम को बैकिंग इंस्टेंस वैरिएबल को असाइन करें। चूंकि -copy विधि हमेशा एक गैर-परिवर्तनीय ऑब्जेक्ट को वापस करने के लिए लागू की जाती है ([aMutableString copy] निष्पादित करने से एनएसएसटींग वापस आ जाएगी) और यह भी सेट करें कि यह संपत्ति हमेशा एक गैर-परिवर्तनीय प्रतिलिपि संग्रहित करेगी।