objective c - एनएसएसटींग संपत्ति: कॉपी या रखरखाव?




objective-c cocoa (7)

मान लें कि मेरे पास string प्रॉपर्टी नाम के साथ SomeClass नामक एक क्लास है:

@interface SomeClass : NSObject
{
    NSString* name;
}

@property (nonatomic, retain) NSString* name;

@end

मैं समझता हूं कि नाम को NSMutableString असाइन किया जा सकता है, इस मामले में इससे ग़लत व्यवहार हो सकता है।

  • सामान्य रूप से तारों के लिए, क्या हमेशा retain बजाय copy विशेषता का उपयोग करना एक अच्छा विचार है?
  • क्या "प्रतिस्थापित" संपत्ति किसी भी तरह से "retain-ed" संपत्ति से कम कुशल है?

सामान्य रूप से तारों के लिए, क्या हमेशा बनाए रखने के बजाय प्रतिलिपि विशेषता का उपयोग करना एक अच्छा विचार है?

हां - आम तौर पर प्रतिलिपि विशेषता का उपयोग करें।

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

क्या "प्रतिस्थापित" संपत्ति किसी भी तरह से "retain-ed" संपत्ति से कम कुशल है?

  • यदि आपकी संपत्ति को एनएसएसटींगिंग उदाहरण पास किया जा रहा है, तो जवाब " नहीं " है - प्रतिलिपि बनाए रखने से कम कुशल नहीं है।
    (यह कम कुशल नहीं है क्योंकि एनएसएसटींग वास्तव में एक प्रतिलिपि करने के लिए पर्याप्त स्मार्ट नहीं है।)

  • यदि आपकी संपत्ति एनएसएमयूटेबल स्ट्रिंग इंस्टेंस पास कर दी गई है तो उत्तर " हां " है - प्रतिलिपि बनाए रखने से कम कुशल है।
    (यह कम कुशल है क्योंकि वास्तविक स्मृति आवंटन और प्रति होना आवश्यक है, लेकिन यह शायद एक वांछनीय बात है।)

  • आम तौर पर एक "प्रतिलिपि" संपत्ति को कम कुशल होने की संभावना होती है - हालांकि NSCopying प्रोटोकॉल के उपयोग के माध्यम से, एक वर्ग को लागू करना संभव है जो प्रतिलिपि बनाने के लिए प्रतिलिपि बनाने के लिए "उतना ही कुशल" है। एनएसएसटींग उदाहरण इस का एक उदाहरण हैं।

आम तौर पर (न केवल एनएसएसटींग के लिए), मुझे "बनाए रखने" के बजाय "प्रतिलिपि" का उपयोग कब करना चाहिए?

जब आप संपत्ति की आंतरिक स्थिति चेतावनी के बिना बदलना नहीं चाहते हैं तो आपको हमेशा copy उपयोग करना चाहिए। यहां तक ​​कि अपरिवर्तनीय वस्तुओं के लिए - ठीक से लिखित अपरिवर्तनीय वस्तुएं प्रतिलिपि प्रतिलिपि संभालेंगी (अपरिवर्तनीयता और NSCopying संबंध में अगला अनुभाग देखें)।

ऑब्जेक्ट्स को retain प्रदर्शन कारण हो सकते हैं, लेकिन यह रखरखाव ओवरहेड के साथ आता है - आपको अपने कोड के बाहर आंतरिक स्थिति बदलने की संभावना का प्रबंधन करना होगा। जैसा कि वे कहते हैं - अंतिम अनुकूलित करें।

लेकिन, मैंने अपनी कक्षा को अपरिवर्तनीय होने के लिए लिखा - क्या मैं इसे "बनाए रख" नहीं सकता?

नहीं - copy । यदि आपकी कक्षा वास्तव में अपरिवर्तनीय है तो copy का उपयोग होने पर आपकी कक्षा को स्वयं वापस करने के लिए NSCopying प्रोटोकॉल को लागू करने का सबसे अच्छा अभ्यास है। अगर तुम यह करते हो:

  • जब वे copy उपयोग करते हैं तो आपकी कक्षा के अन्य उपयोगकर्ता प्रदर्शन लाभ प्राप्त करेंगे।
  • copy एनोटेशन आपके स्वयं के कोड को अधिक रखरखाव बनाता है - copy एनोटेशन इंगित करता है कि आपको वास्तव में इस ऑब्जेक्ट को अन्यत्र बदलते राज्य के बारे में चिंता करने की आवश्यकता नहीं है।

इस उदाहरण के माध्यम से कॉपी और रखरखाव की व्याख्या की जा सकती है:

NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];

Person *p = [[[Person alloc] init] autorelease];
p.name = someName;

[someName setString:@"Debajit"];

अगर संपत्ति प्रकार की प्रतिलिपि है तो,

[Person name] स्ट्रिंग के लिए एक नई प्रतिलिपि बनाई जाएगी जो कुछ [Person name] स्ट्रिंग की सामग्री someName । अब कुछ someName स्ट्रिंग पर किसी भी ऑपरेशन का [Person name] पर कोई प्रभाव नहीं पड़ेगा।

[Person name] और someName [Person name] तारों में अलग-अलग स्मृति पते होंगे।

लेकिन बनाए रखने के मामले में,

दोनों [Person name] एक ही स्मृति पता को somename स्ट्रिंग के रूप में रखेगा, केवल somename स्ट्रिंग की बनाए रखने की गणना 1 से बढ़ा दी जाएगी।

तो somename स्ट्रिंग में कोई भी परिवर्तन [Person name] स्ट्रिंग में दिखाई देगा।


एनएसएसटींग संपत्ति घोषित करने के लिए आपको हर समय प्रतिलिपि का उपयोग करना चाहिए

@property (nonatomic, copy) NSString* name;

आपको इन्हें अधिक जानकारी के लिए पढ़ना चाहिए कि क्या यह अपरिवर्तनीय स्ट्रिंग देता है (यदि म्यूटेबल स्ट्रिंग पास हो जाती है) या एक बनाए रखा स्ट्रिंग देता है (यदि अपरिवर्तनीय स्ट्रिंग पास की गई हो)

एनएससीपीआईंग प्रोटोकॉल संदर्भ

कक्षा और इसकी सामग्री अपरिवर्तनीय होने पर एक नई प्रतिलिपि बनाने के बजाय मूल को बनाए रखकर एनएससीपीआईपी लागू करें

मूल्य वस्तुएं

तो, हमारे अपरिवर्तनीय संस्करण के लिए, हम बस यह कर सकते हैं:

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

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


मैं इस सरल नियम का पालन करने की कोशिश करता हूं:

  • क्या मैं इस समय वस्तु के मूल्य को उस समय पर पकड़ना चाहता हूं जब मैं इसे अपनी संपत्ति में निर्दिष्ट कर रहा हूं? प्रतिलिपि का प्रयोग करें।

  • क्या मैं ऑब्जेक्ट को पकड़ना चाहता हूं और मुझे परवाह नहीं है कि वर्तमान में इसके आंतरिक मूल्य क्या हैं या भविष्य में होंगे? मजबूत (बनाए रखें) का प्रयोग करें।

उदाहरण के लिए: क्या मैं "लिसा मिलर" ( प्रतिलिपि ) नाम पर पकड़ना चाहता हूं या मैं लिसा मिलर ( मजबूत ) व्यक्ति को पकड़ना चाहता हूं? उसका नाम बाद में "लिसा स्मिथ" में बदल सकता है, लेकिन वह अभी भी वही व्यक्ति होगी।


यदि स्ट्रिंग बहुत बड़ी है तो कॉपी प्रदर्शन को प्रभावित करेगी और बड़ी स्ट्रिंग की दो प्रतियां अधिक मेमोरी का उपयोग करेंगी।


@interface TTItem : NSObject    
@property (nonatomic, copy) NSString *name;
@end

{
    TTItem *item = [[TTItem alloc] init];    
    NSString *test1 = [NSString stringWithFormat:@"%d / %@", 1, @"Go go go"];  
    item.name = test1;  
    NSLog(@"-item.name: point = %p, content = %@; test1 = %p", item.name, item.name, test1);  
    test1 = [NSString stringWithFormat:@"%d / %@", 2, @"Back back back"];  
    NSLog(@"+item.name: point = %p, content = %@, test1 = %p", item.name, item.name, test1);
}

Log:  
    -item.name: point = 0x9a805a0, content = 1 / Go go go; test1 = 0x9a805a0  
    +item.name: point = 0x9a805a0, content = 1 / Go go go, test1 = 0x9a84660




cocoa-touch