2010-01-19 27 views
7

यह एक अपरिवर्तनीय स्ट्रिंग वस्तु का उत्पादन:कोको: यह पता लगाने के लिए कि कोई एनएसएसटींग अपरिवर्तनीय या परिवर्तनीय है या नहीं?

NSString* myStringA = @"A"; //CORRECTED FROM: NSMutableString* myStringA = @"A"; 

यह एक अस्थायी स्ट्रिंग वस्तु का उत्पादन:

NSMutableString* myStringB = [NSMutableString stringWithString:@"B"]; 

लेकिन दोनों वस्तुओं वस्तु की ही तरह, "NSCFString" के रूप में रिपोर्ट कर रहे हैं:

NSLog(@"myStringA is type: %@, myStringB is type: %@", 
[myStringA class], [myStringB class]); 

तो इन वस्तुओं को आंतरिक रूप से अलग करना क्या है, और मैं इसके लिए परीक्षण कैसे करूं, ताकि मैं आसानी से यह निर्धारित कर सकूं कि कोई रहस्य स्ट्रिंग चर अपरिपक्व है या नहीं इससे कुछ बुरा करने से पहले सक्षम या परिवर्तनीय?

+0

फिलिप का कोड नीचे - अगर ([myStringB isKindOfClass: [NSMutableString class]]) - व्यावहारिक समस्या को हल करता है और हल करता है। – StringSection

+0

मैं अभी भी उत्सुक हूं कि एक अपरिवर्तनीय और परिवर्तनीय स्ट्रिंग के बीच का अंतर आंतरिक रूप से कैसे प्रदर्शित किया जा रहा है, और यदि इसे सीधे पाया जा सकता है (वास्तविक "प्रकार की वस्तु" एनएसएलओजी के साथ मुद्रित)। – StringSection

+1

सुधार: मुझे गलती हुई थी, कोड - अगर ([myStringB isKindOfClass: [NSMutableString क्लास]]) - सब के बाद काम नहीं कर रहा है। यह सच है कि स्ट्रिंग NSString या NSMutableString है या नहीं। जैसा कि फिलिप नीचे इंगित करता है (अलग-अलग कोड के साथ अपने अब संपादित उत्तर में) जाहिर तौर पर रनटाइम पर म्यूटेबल बनाम अपरिवर्तनीय वस्तुओं का पता लगाने के लिए कोई दस्तावेज नहीं है। – StringSection

उत्तर

4

यह निर्धारित करने के लिए कोई (दस्तावेज) तरीका नहीं है कि कोई स्ट्रिंग रनटाइम पर परिवर्तनीय है या नहीं।

आप निम्नलिखित काम करेगा में से एक उम्मीद होती है, लेकिन उनमें से कोई भी काम:

[[s class] isKindOfClass:[NSMutableString class]]; // always returns false 
[s isMemberOfClass:[NSMutableString class]]; // always returns false 
[s respondsToSelector:@selector(appendString)]; // always returns true 

अधिक जानकारी यहाँ है, हालांकि यह समस्या के साथ तुम्हारी मदद नहीं करता है:

http://www.cocoabuilder.com/archive/cocoa/111173-mutability.html

+0

काम नहीं करता है: एनएसएमयूटेबलस्ट्रिंग * लाला = @ "लाला"; \t अगर ([लाला isKindOfClass: [NSMutableString वर्ग]]) एनएसएलओजी (@ "उत्परिवर्ती वर्ग"); - लॉग संदेश दिखाता है, हालांकि ऑब्जेक्ट अपरिवर्तनीय है – Vladimir

+0

बेशक यह काम नहीं करता है, क्योंकि कोड गलत है। ** एनएसएमयूटेबलस्ट्रिंग * लाला = @ "लाला" ** अवैध कोड है। –

+0

क्षमा करें दोस्तों - एनएसएमयूटेबलस्ट्रिंग * myStringA = @ "ए"; एक टाइपो था - मूल संदेश में अब सही किया गया। – StringSection

3

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

BOOL isMutable(id object) 
{ 
    id copy = [object copy]; 
    BOOL copyIsADifferentObject = (copy != object); 
    [copy release]; 
    return copyIsADifferentObject; 
} 

अस्वीकरण: निश्चित रूप से कोई गारंटी नहीं है कि कॉपी अपरिवर्तनीय प्रकारों के लिए बनाए रखने के बराबर है। आप सुनिश्चित कर सकते हैं कि यदि isMutable कोई नहीं लौटाता है तो यह उत्परिवर्तनीय नहीं है इसलिए फ़ंक्शन को शायद canBeMutable नाम दिया जाना चाहिए। असली दुनिया में हालांकि, यह एक बहुत ही सुरक्षित धारणा है कि अपरिवर्तनीय प्रकार (एनएसएसटींग, एनएसएआरएआरई) इस अनुकूलन को लागू करेगा। NSDictionary जैसी बुनियादी चीजों सहित बहुत सारे कोड हैं जो अपरिवर्तनीय प्रकारों से तेज़ प्रति की अपेक्षा करते हैं।

12

दस्तावेज़ों में काफी लंबा स्पष्टीकरण शामिल है कि क्यों ऐप्पल यह नहीं करना चाहता कि आप ऐसा क्यों करें और क्यों वे स्पष्ट रूप से Receiving Mutable Objects में इसका समर्थन नहीं करते हैं। सार है:

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

मुझे उनके NSView उदाहरण को समझने में सबसे आसान लगता है, और यह मूल कोको समस्या को दर्शाता है। आपके पास एक एनएसएमयूटेबलएरे है जिसे "तत्व" कहा जाता है जिसे आप सरणी के रूप में उजागर करना चाहते हैं, लेकिन कॉलर्स को गड़बड़ नहीं करना चाहते हैं। आपके पास कई विकल्प हैं:

  1. अपने एनएसएमयूटेबलएरे को एनएसएआरएआरई के रूप में पेश करें।
  2. अनुरोध करते समय हमेशा एक गैर-परिवर्तनीय प्रतिलिपि बनाएं
  3. तत्वों को एनएसएआरएआरई के रूप में स्टोर करें और हर बार जब यह उत्परिवर्तित हो जाए तो एक नई सरणी बनाएं।

मैंने इन सभी को विभिन्न बिंदुओं पर किया है। # 1 अब तक का सबसे सरल और तेज़ समाधान है। यह भी खतरनाक है, क्योंकि सरणी कॉलर की पीठ के पीछे उत्परिवर्तित हो सकती है। लेकिन ऐप्पल इंगित करता है कि वे कुछ मामलों में क्या करते हैं (एनएसवी व्यू में -subviews के लिए चेतावनी नोट करें)। मैं पुष्टि कर सकता हूं कि # 2 और # 3 अधिक सुरक्षित हैं, लेकिन वे बड़ी प्रदर्शन समस्याएं पैदा कर सकते हैं, शायद यही कारण है कि ऐप्पल ने इन्हें एक्सेस-इन सदस्यों जैसे सब्सव्यूज़ पर उपयोग न करने का विकल्प चुना है।

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

इसके लिए फिक्स एक म्यूटेबल डेटा संरचना के किसी प्रकार की तेज़ प्रति-लिखने योग्य अपरिवर्तनीय संस्करण होगा। इस तरह # 2 संभवतः सभ्य प्रदर्शन के साथ किया जा सकता है। मैं एनएसएआरएआर क्लस्टर में बदलाव की कल्पना कर सकता हूं जो इसकी अनुमति देगा, लेकिन यह आज कोको में मौजूद नहीं है (और सामान्य मामले में एनएसएआरएआर प्रदर्शन को प्रभावित कर सकता है, जिससे इसे गैर-स्टार्टर बना दिया जा सकता है)। यहां तक ​​कि यदि हमारे पास था, तो शायद वहां बहुत अधिक कोड है जो मौजूदा व्यवहार पर निर्भर करता है ताकि कभी भी उत्परिवर्तन आत्मनिरीक्षण पर भरोसा किया जा सके।

+1

आप उत्परिवर्ती सरणी एक्सेसर्स (http://developer.apple.com/documentation/Cocoa/Conceptual/ModelObjects/Articles/moAccessorMethods.html) को कार्यान्वित और उजागर करके और अन्य वर्गों में उनका उपयोग करके # 3 के साथ प्रदर्शन समस्या को हल कर सकते हैं। इस तरह, म्यूटेबल सरणी तक सीधी पहुंच निजी बनी हुई है, लेकिन आप अस्थायी सरणी नहीं बना रहे हैं और फेंक रहे हैं। –

+1

@ पीएच यह सच है और मुझे केवीसी समाधान को कवर करना चाहिए था। समस्या यह है कि ऐसे कई मामले हैं जहां कॉलर को वास्तव में एक संग्रह की आवश्यकता होती है (आम तौर पर किसी और को मांगने के लिए)। मैंने अक्सर तत्व एनीम्युलेटर जैसे कुछ को उजागर करके हल किया है, जो कॉलर एक स्नैपशॉट में बदल सकता है अगर वह चाहता है। इस दृष्टिकोण के साथ समस्या कॉलर और कॉल के लिए आवश्यक अतिरिक्त कोड की मात्रा है। यह प्रबुद्ध है कि ऐप्पल, यहां तक ​​कि यूआईवी व्यू के नए कोड में, ने एनएसएमयूटेबलएरे "सबव्यूव्स" को एनएसएआरएआरई के रूप में बेनकाब करना और पूर्ण केवीसी प्रदान नहीं करना चुना। –

+0

एचएम? मैं इस बात पर स्पष्ट नहीं हूं कि आप किस समस्या के बारे में बात कर रहे हैं या आपका समाधान क्या है। ब्लॉग पोस्ट और/या पेस्टबिन? –

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

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