मैं NSMutableArray को NSArray में कैसे बदलूँ?


381

मैं NSMutableArray को NSArray में कैसे परिवर्तित करूं ?


12
सिर्फNSArray *array = [mutableArray copy];
बेरिलियम 20

1
NSArray *array = mutableArray;
vladof81

4
बेरिलियम: बिल्कुल सही। vladof81: बिल्कुल नहीं।
gnasher729

जवाबों:


511
NSArray *array = [mutableArray copy];

Copyअपरिवर्तनीय प्रतियां बनाता है। यह काफी उपयोगी है क्योंकि Apple विभिन्न अनुकूलन कर सकता है। उदाहरण के लिए copyएक अपरिवर्तनीय सरणी पर भेजने से केवल ऑब्जेक्ट और रिटर्न ही बरकरार रहता है self

यदि आप कचरा संग्रहण या एआरसी का उपयोग नहीं करते हैं तो याद रखें कि -copyवह वस्तु बरकरार रखती है।


2
यह उत्तर बहुत अच्छा है, लेकिन मैं उन डॉक्स से कैसे कह सकता हूं जो copyएक सामान्य NSArray बनाता है और NSMutableArray नहीं?
डेन रोसेनस्टार्क

22
@ यार: आप NSCopying के दस्तावेज़ीकरण को देखते हैं। इसमें कहा गया है: copyWithZone यदि प्राप्त की गई "अपरिवर्तनीय बनाम उत्परिवर्तित" वस्तु पर
जॉर्ज शॉर्ली

1
बहुत साफ - मैं इसे m5h के समाधान के लिए पसंद करता हूं। दोनों और अधिक कुशल।
डेविड स्नेबेल-कॉंट

1
मैं डेविड से सहमत हूं, इस प्रतिक्रिया को इंगित करने के लिए मेरी प्रतिक्रिया को अपडेट किया।
हॉलिडे

2
@ ब्रैड: इसका मतलब है कि ऐसी कक्षाएं जिनका परस्पर और अपरिवर्तनीय कार्यान्वयन दोनों हैं। उदाहरण के लिए NSArrayऔर NSMutableArray, NSStringऔर NSMutableString। लेकिन उदाहरण के लिए नहीं NSViewControllerजिसमें हमेशा परिवर्तनशील स्थिति होती है।
जॉर्ज शॉली

361

एक NSMutableArrayउपवर्ग है, NSArrayइसलिए आपको हमेशा बदलने की आवश्यकता नहीं होगी, लेकिन यदि आप यह सुनिश्चित करना चाहते हैं कि सरणी को संशोधित नहीं किया जा सकता है तो आप NSArrayइन तरीकों में से किसी एक को बना सकते हैं, इस पर निर्भर करता है कि आप इसे ऑटोरेल्ड चाहते हैं या नहीं:

/* Not autoreleased */
NSArray *array = [[NSArray alloc] initWithArray:mutableArray];

/* Autoreleased array */
NSArray *array = [NSArray arrayWithArray:mutableArray];

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


7
क्या मैं सिर्फ (NSArray *) myMutableArray कर सकता हूं?
वोजतो

2
हां, जैसा कि NSMutableArray NSArray का एक उपवर्ग है जो मान्य है।
हॉलस्की

4
हालाँकि, (NSArray *) को कास्ट करना अभी भी कास्ट (NSMutable *) को कास्ट करता है। कि मामला नहीं है?
शार्वे नोव

1
@ शेरवे: हाँ, यह सही है। यदि आप वोट नहीं डालते हैं तो आपको चेतावनी मिल जाएगी, लेकिन सीधे सुपरक्लास को एक उपवर्ग को सौंप दें। आमतौर पर, आप एक अपरिवर्तनीय प्रति वापस करना चाहते हैं, क्योंकि यह सुनिश्चित करने का एकमात्र तरीका है, कि आपका सरणी वास्तव में संशोधित नहीं होगा।
जॉर्ज शॉर्ली

1
पूर्व में इसे "Upcasting" (NSArray *) myMutableArray के रूप में जाना जाता है और व्युत्क्रम को "डाउनकास्टिंग" कहा जाता है
फ्रांसिस्को Gutiérrez

113

मुझे 2 मुख्य समाधान पसंद हैं:

NSArray *array = [NSArray arrayWithArray:mutableArray];

या

NSArray *array = [mutableArray copy];

प्राथमिक अंतर मैं उन्हें देख उनका व्यवहार जब mutableArray नहीं के बराबर है है :

NSMutableArray *mutableArray = nil;
NSArray *array = [NSArray arrayWithArray:mutableArray];
// array == @[] (empty array)

NSMutableArray *mutableArray = nil;
NSArray *array = [mutableArray copy];
// array == nil

यह तो गलत है। बस जाँच की गई। [mutableArray कॉपी] भी एक खाली सरणी देता है।
दुरज़्नो

@durazno यह गलत नहीं है। अपने परीक्षण को दोबारा जांचें। यदि [mutableArray कॉपी] एक खाली सरणी लौटा रहा है, तो mutableArray एक खाली सरणी रहा होगा। मेरा जवाब केवल तभी लागू होता है जब mutableArray शून्य होता है।
रिचर्ड वेनेबल जूल

हालांकि यह सच है, मुझे लगता है कि आप अपने उदाहरण में एक अधिक मौलिक सच्चाई याद कर रहे हैं। चूँकि आपने mutableArray को nil किया है, इसलिए [mutableArray copy]इसे सरल बनाया जा सकता है [nil copy]। वस्तुनिष्ठ-ग में शून्य पर भेजा गया कोई भी संदेश हमेशा शून्य होगा। "कुछ भी नहीं" और "इसमें कुछ नहीं के साथ एक सरणी" के बीच अंतर को याद रखना महत्वपूर्ण है।
mkirk

@mkirk आइए इस सवाल पर ध्यान न दें: "मैं NSAutableArray को NSAray में कैसे बदलूं?" 2 प्राथमिक समाधान हैं, और उनके बीच प्राथमिक अंतर यह है कि उत्परिवर्तित सरणी शून्य होने पर वे कैसे व्यवहार करते हैं।
रिचर्ड वेनेबल


5

उद्देश्य सी

नीचे NSMutableArray को NSArray में बदलने का तरीका है:

//oldArray is having NSMutableArray data-type.
//Using Init with Array method.
NSArray *newArray1 = [[NSArray alloc]initWithArray:oldArray];

//Make copy of array
NSArray *newArray2 = [oldArray copy];

//Make mutablecopy of array
NSArray *newArray3 = [oldArray mutableCopy];

//Directly stored NSMutableArray to NSArray.
NSArray *newArray4 = oldArray;

तीव्र

स्विफ्ट 3.0 में नया डेटा टाइप एरे हैletकीवर्ड का उपयोग करके ऐरे को घोषित करें तो वह NSArray बन जाएगा और यदि varकीवर्ड का उपयोग करने की घोषणा करता है तो यह NSMutableArray बन जाएगा

नमूना कोड:

let newArray = oldArray as Array

स्विफ्ट वाला हिस्सा पूरी तरह से सही नहीं है। उत्परिवर्तनीय / अपरिवर्तनीय s और / s के बीच अंतर के लिए यहां और यहां देखें । वे एक जैसे नहीं हैं। ArrayNSArrayNSMutableArray
ब्रूनो ईली


2
NSArray *array = mutableArray;

इस [mutableArray copy] एंटीपैटर्न सभी नमूना कोड से अधिक है। फेंकने योग्य उत्परिवर्ती सरणियों के लिए ऐसा करना बंद करें जो क्षणिक हैं और वर्तमान दायरे के अंत में निपटाए जाते हैं।

ऐसा कोई तरीका नहीं है कि रनटाइम एक उत्परिवर्तित सारणी की व्यर्थ नकल को अनुकूलित कर सके जो कि केवल दायरे से बाहर जाने के बारे में है, 0 से घटाया गया और अच्छे के लिए डील किया गया।


NSMutableArrayएक NSArrayचर को असाइन करने से इसे कवर नहीं किया जाएगा (जो कि ओपी का सवाल है)। इस तरह के मूल्य को उजागर करना (उदाहरण के लिए रिटर्न वैल्यू या संपत्ति के रूप में) के परिणामस्वरूप बहुत मुश्किल से मुद्दों को डिबग किया जा सकता है अगर उस मूल्य को अप्रत्याशित रूप से उत्परिवर्तित किया गया था। यह दोनों आंतरिक और बाह्य उत्परिवर्तन पर लागू होता है क्योंकि उत्परिवर्तनीय मूल्य साझा किया जाता है।
डेविड रोनकविस्ट

उस सरणी को बदलने के लिए आपको [NSMutableArray arrayWithArray: ... या ऐसा कुछ करना होगा।
एंटोन ट्रोपास्को

जरुरी नहीं। बस इसे एक NSMutableArrayवैरिएबल में असाइन करना पर्याप्त है। चूँकि ऑब्जेक्ट कभी भी एक उत्परिवर्ती सारणी नहीं होता है, इसलिए उस पर उत्परिवर्तन विधियों को कॉल करना सफल होगा और साझा किए गए डेटा को म्यूट करेगा। यदि दूसरी ओर मूल परिवर्तनशील सरणी की प्रतिलिपि बनाई गई थी - इसे एक अपरिवर्तनीय सरणी में बदलना - और फिर एक NSMutableArrayचर के लिए असाइन किया गया था और उस पर कॉल करने के तरीकों को बदलना था, तो वे कॉल doesNotRespondToSelectorत्रुटियों के साथ विफल हो जाएंगे क्योंकि ऑब्जेक्ट जो उत्परिवर्तन विधि कॉल प्राप्त करता है, वह है वास्तव में अपरिवर्तनीय और उन तरीकों का जवाब नहीं है।
डेविड रोनक्विस्ट

ठीक है, यह डेवलपर्स के लिए कुछ योग्यता हो सकता है जो टाइपर रूपांतरण assigments के बारे में संकलक चेतावनी को ध्यान में नहीं रखते हैं
एंटोन ट्रोपास्को

1

यदि आप परिवर्तनशीलता के माध्यम से एक सरणी का निर्माण कर रहे हैं और फिर एक अपरिवर्तनीय संस्करण वापस करना चाहते हैं, तो आप विरासत के माध्यम से बस "सरणी" के रूप में उत्परिवर्तित सरणी को वापस कर सकते हैं।

- (NSArray *)arrayOfStrings {
    NSMutableArray *mutableArray = [NSMutableArray array];
    mutableArray[0] = @"foo";
    mutableArray[1] = @"bar";

    return mutableArray;
}

यदि आप एक अपरिवर्तनीय NSArray के रूप में (तकनीकी रूप से अभी भी परिवर्तनशील) रिटर्न ऑब्जेक्ट का इलाज करने के लिए कॉल करने वाले पर "भरोसा" करते हैं, तो यह इससे सस्ता विकल्प है [mutableArray copy]

Apple कॉन्सर्ट:

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

उपरोक्त अभ्यास पर यहां और अधिक विस्तार से चर्चा की गई है:

सर्वोत्तम प्रैक्टिस: यदि रिटर्न टाइप NSArray है, तो mutableArray.copy या mutableArray लौटें


0

मैं स्विफ्ट 3 में उत्तर की खोज कर रहा था और इस प्रश्न को खोज में पहली बार परिणाम के रूप में दिखाया गया था और मुझे इससे उत्तर की प्रेरणा मिली, इसलिए यहां स्विफ्ट 3 कोड है

let array: [String] = nsMutableArrayObject.copy() as! [String]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.