सवाल कॉपी और mutableCopy कैसे एनएसएआरएआरई और एनएसएमयूटेबलएरे पर लागू होते हैं?


के बीच क्या अंतर है copy तथा mutableCopy जब किसी पर इस्तेमाल किया जाता है NSArray या एक NSMutableArray?

यह मेरी समझ है; क्या यह सही है?

// ** NSArray **
NSArray *myArray_imu = [NSArray  arrayWithObjects:@"abc", @"def", nil];

// No copy, increments retain count, result is immutable
NSArray *myArray_imuCopy = [myArray_imu copy];

// Copys object, result is mutable 
NSArray *myArray_imuMuta = [myArray_imu mutableCopy];

// Both must be released later

// ** NSMutableArray **
NSMutableArray *myArray_mut = [NSMutableArray arrayWithObjects:@"A", @"B", nil];

// Copys object, result is immutable
NSMutableArray *myArray_mutCopy = [myArray_mut copy];

// Copys object, result is mutable
NSMutableArray *myArray_mutMuta = [myArray_mut mutableCopy];

// Both must be released later

63
2018-01-04 20:56


मूल


आपके संपादन में आपको गलती है; सुनिश्चित नहीं है कि यह एक टाइपो या गलतफहमी है। पहले कोड ब्लॉक में, परिवर्तनीय myArray_imuMuta जिसे mutableCopy से असाइन किया गया है परिवर्तनशील, आपकी टिप्पणी के संकेत के रूप में अपरिवर्तनीय नहीं है। - Asher Dunn
धन्यवाद, यह एक गलती थी, मैं एक्सकोड के साथ भ्रमित हो रहा था, "चेतावनी एनएसएआरएआरई ऐड-एडऑब्जेक्ट / -removeObjectAtIndex का जवाब नहीं दे सकती है। मैं myArray_imuMuta को NSMutableArray में बदल दूंगा। - fuzzygoat
@JamesHarnett - कृपया "एआरसी संगतता" के नाम पर संपादन को रोकें - देखें यह मेटा पोस्ट क्यों के लिए - Krease


जवाब:


copy तथा mutableCopy विभिन्न प्रोटोकॉल में परिभाषित हैं (NSCopying तथा NSMutableCopying, क्रमशः), और NSArray दोनों के अनुरूप है। mutableCopy के लिए परिभाषित किया गया है NSArray (न सिर्फ NSMutableArray) और आपको मूल रूप से अपरिवर्तनीय सरणी की एक परिवर्तनीय प्रतिलिपि बनाने की अनुमति देता है:

// create an immutable array
NSArray *arr = [NSArray arrayWithObjects: @"one", @"two", @"three", nil ];

// create a mutable copy, and mutate it
NSMutableArray *mut = [arr mutableCopy];
[mut removeObject: @"one"];

सारांश:

  • आप के परिणाम पर निर्भर कर सकते हैं mutableCopy मूल प्रकार के बावजूद, परिवर्तनीय होने के लिए। सरणी के मामले में, परिणाम एक होना चाहिए NSMutableArray
  • आप नही सकता के परिणाम पर निर्भर करता है copy उत्परिवर्तनीय होने के लिए! copyआईएनजी NSMutableArray  हो सकता है एक वापसी NSMutableArray, क्योंकि यह मूल वर्ग है, लेकिन copyकिसी भी मनमाने ढंग से NSArray उदाहरण नहीं होगा।

संपादित करें: मार्क बेस्से के जवाब के प्रकाश में अपना मूल कोड दोबारा पढ़ें। जब आप अपनी सरणी की एक प्रति बनाते हैं, तो निश्चित रूप से आप कॉपी के साथ जो भी करते हैं उसके बावजूद आप मूल को संशोधित कर सकते हैं। copy बनाम mutableCopy प्रभावित करता है कि क्या नई सरणी उत्परिवर्तनीय है।

2 संपादित करें: मेरी (झूठी) धारणा तय की है कि NSMutableArray -copy एक वापस आ जाएगा NSMutableArray


69
2018-01-04 21:11



एक NSMutableArray को भेजना -कोपी सामान्य रूप से एक और म्यूटेबल सरणी नहीं लौटाता है। यह निश्चित रूप से ऐसा कर सकता है, लेकिन सामान्य स्थिति में, यह एक अपरिवर्तनीय, निरंतर समय का उपयोग, सरणी देता है। - Mark Bessey
ओह, तुम सही हो। मैंने ओपी के कोड को गलत तरीके से पढ़ा और सोचा कि वह -कोपी के परिणाम को संशोधित कर रहा था। यह एनएसएमयूटेबलएरे के लिए एक और म्यूटेबल सरणी लौटने के लिए उतना ही समझ में आएगा, इसलिए मैंने (गलत तरीके से) माना कि यह मामला था। - Asher Dunn
क्या मुझे कुछ याद आ रहा है क्योंकि मुझे [mut remove: @ "one"] का कोई संदर्भ नहीं मिल रहा है; यह नहीं होना चाहिए [mut removeObjectIdenticalTo: @ "one"]; मैं बस इसे पढ़ने और सीखने की कोशिश करने वालों के लिए स्पष्टीकरण देना चाहता हूं? - fuzzygoat
ओह, यह होना चाहिए [mut removeObject: @ "one"]; निकालें ऑब्जेक्ट का उपयोग करता है- मैचों को निर्धारित करने के लिए एक्सेल, और दो तारों को बराबर माना जाता है यदि उनके पास समान सामग्री है। निकालेंऑब्जेक्ट इडेंटिकल केवल हटाने के लिए सटीक वस्तु पारित (यह ऑब्जेक्ट पते की तुलना करता है, सामग्री नहीं)। [mut removeObjectIdenticalTo: @ "one"] एक नया अस्थायी NSString ऑब्जेक्ट बनाता है, जो सरणी में नहीं है, और इसलिए सरणी से हटाया नहीं जा सकता है। - Asher Dunn
"एक एनएसएमयूटेबलएरे की प्रतिलिपि एक एनएसएमयूटेबलएरे वापस कर सकती है" नहीं, यह कभी भी एनएसएमयूटेबलएरे नहीं देता है। देख developer.apple.com/library/mac/documentation/Cocoa/Conceptual/... "जहां अवधारणा" अपरिवर्तनीय बनाम उत्परिवर्तनीय "किसी ऑब्जेक्ट पर लागू होती है, एनएससीपीआईपी अपरिवर्तनीय प्रतियां उत्पन्न करती है चाहे मूल अपरिवर्तनीय है या नहीं।" - user102008


मुझे लगता है कि आपने गलत व्याख्या की होगी कि प्रतिलिपि और mutableCopy कैसे काम करते हैं। आपके पहले उदाहरण में, myArray_COPY myArray की एक अपरिवर्तनीय प्रति है। प्रतिलिपि बनाने के बाद, आप मूल myArray की सामग्री में हेरफेर कर सकते हैं, और myArray_COPY की सामग्री को प्रभावित नहीं कर सकते हैं।

दूसरे उदाहरण में, आप myArray की एक म्यूटेबल प्रतिलिपि बनाते हैं, जिसका अर्थ है कि आप किसी अन्य को प्रभावित किए बिना सरणी की प्रतिलिपि को संशोधित कर सकते हैं।

अगर मैं myArray_COPY से वस्तुओं को सम्मिलित / निकालने का प्रयास करने के लिए पहला उदाहरण बदलता हूं, तो यह विफल हो जाता है, जैसा कि आप उम्मीद करेंगे।


शायद एक सामान्य उपयोग-मामले के बारे में सोचने में मदद मिलेगी। यह अक्सर ऐसा होता है कि आप एक विधि लिख सकते हैं जो एक लेता है NSArray * पैरामीटर, और मूल रूप से बाद में उपयोग के लिए इसे स्टोर करता है। आप इसे इस तरह से कर सकते हैं:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects retain];
}

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

यदि आप इसके बजाय ऐसा करते हैं:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects copy];
}

.. तब प्रतिलिपि विधि के समय सरणी की सामग्री का एक स्नैपशॉट बनाता है।


8
2018-01-04 21:12





"प्रतिलिपि" विधि NSCopying प्रोटोकॉल को लागू करके बनाई गई वस्तु को प्रतिलिपि बनाता है CopyWithZone:

यदि आप एनएसएसटींग को प्रतिलिपि संदेश भेजते हैं:

NSString* myString;

NSString* newString = [myString copy];

वापसी मूल्य एक एनएसएसटींग होगा (म्यूटेबल नहीं)


MutableCopy विधि NSMutableCopying प्रोटोकॉल के mutableCopyWithZone को लागू करके बनाई गई वस्तु को वापस लाती है:

भेजकर:

NSString* myString;

NSMutableString* newString = [myString mutableCopy];

वापसी मूल्य मर्जी उत्परिवर्तनीय हो।


सभी मामलों में, ऑब्जेक्ट को प्रोटोकॉल को कार्यान्वित करना होगा, यह दर्शाता है कि यह नई प्रति ऑब्जेक्ट बनाएगा और इसे आपके पास वापस कर देगा।


एनएसएआरएआरई के मामले में उथले और गहरी प्रतिलिपि के संबंध में जटिलता का एक अतिरिक्त स्तर है।

एनएसएआरएआरई की एक उथली प्रतिलिपि केवल मूल सरणी की वस्तुओं को संदर्भों की प्रतिलिपि बनायेगी और उन्हें नई सरणी में रखेगी।

नतीजा यह है कि:

NSArray* myArray;

NSMutableArray* anotherArray = [myArray mutableCopy];

[[anotherArray objectAtIndex:0] doSomething];

मूल सरणी में इंडेक्स 0 पर ऑब्जेक्ट को भी प्रभावित करेगा।


एक गहरी प्रतिलिपि वास्तव में सरणी में निहित व्यक्तिगत वस्तुओं की प्रतिलिपि बनायेगी। यह प्रत्येक व्यक्तिगत ऑब्जेक्ट को "copyWithZone:" संदेश भेजकर किया जाता है।

NSArray* myArray;

NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:myArray
                                                       copyItems:YES];

Mutable ऑब्जेक्ट प्रतिलिपि के बारे में मेरी गलत धारणा को हटाने के लिए संपादित किया गया


5
2018-01-04 21:25





NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray
                                                           copyItems:YES];

बनाएगा anotherArray जो की एक प्रति है oldArray गहराई से 2 स्तर तक। अगर एक वस्तु है oldArray एक ऐरे है आमतौर पर ज्यादातर अनुप्रयोगों में मामला है।

ठीक है अगर हमें एक की जरूरत है सच गहरी प्रतिलिपि हम उपयोग कर सकते हैं,

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
    [NSKeyedArchiver archivedDataWithRootObject: oldArray]];

इससे यह सुनिश्चित होगा कि सभी स्तरों को वास्तव में प्रत्येक स्तर पर मूल वस्तु की व्यवहार्यता को बनाए रखने की प्रतिलिपि बनाई जाती है।

रॉबर्ट क्लेरेंस डी'एल्मेडा, बैंगलोर, भारत।


5
2017-09-02 16:06



"ट्रू दीप कॉपी" की आपकी अवधारणा वास्तव में अच्छी है .. बिल्कुल वही है जो मैं चाहता हूं ... बहुत बहुत धन्यवाद और आपके लिए +1 ..... - Nirav Gadhiya


आप अपने द्वारा बनाई गई नई प्रति की बजाय, मूल सरणी पर addObject और removeObjectAtIndex को कॉल कर रहे हैं। कॉलिंग कॉपी बनाम mutableCopy केवल वस्तु की नई प्रति की परिवर्तनशीलता को प्रभावित करता है, मूल वस्तु नहीं।


3
2018-01-04 22:56





इसे बस बताने के लिए,

  • प्रतिलिपि एक अपरिवर्तनीय (संशोधित नहीं किया जा सकता है) सरणी की प्रतिलिपि,
  • mutableCopy सरणी की एक mutable (संशोधित किया जा सकता है) प्रतिलिपि देता है।

प्रतिलिपि (दोनों मामलों में) का अर्थ है कि आपको मूल सरणी के ऑब्जेक्ट संदर्भों के साथ "पॉप्युलेट" की एक नई सरणी मिलती है (यानी वही (मूल) ऑब्जेक्ट प्रतियों में संदर्भित होते हैं।

यदि आप mutableCopy में नई ऑब्जेक्ट्स जोड़ते हैं, तो वे mutableCopy के लिए अद्वितीय हैं। यदि आप mutableCopy से ऑब्जेक्ट्स को हटाते हैं, तो उन्हें मूल सरणी से निकाल दिया जाता है।

प्रतिलिपि बनाई गई थी जब मूल सरणी के समय में एक स्नैपशॉट के रूप में दोनों मामलों में प्रतिलिपि के बारे में सोचें।


2
2017-07-05 11:57





मान लीजिये

NSArray *A = xxx; // A with three NSDictionary objects
NSMutableArray *B = [A mutableCopy]; 

बी की सामग्री NSDictionary ऑब्जेक्ट एनएसएमयूटेबल डिक्शनरी नहीं है, क्या यह सही है?


0
2018-05-12 04:28





-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.

आपको इन प्रतिलिपि सामानों के रिटर्न प्रकार को जानना होगा और नई ऑब्जेक्ट को घोषित करते समय एक को आवंटित किया जाएगा, रिटर्न वैल्यू अपरिवर्तनीय या परिवर्तनीय होना चाहिए, अन्यथा संकलक आपको त्रुटि दिखाएगा।

जिस वस्तु को कॉपी किया गया है उसे नए का उपयोग करके संशोधित नहीं किया जा सकता है, वे अब पूरी तरह से दो अलग-अलग वस्तुएं हैं।


0
2017-08-07 06:28