2010-09-13 18 views
78

दोनों निम्नलिखित तुलना सच का मूल्यांकन:समझौता NSString तुलना

1)

@"foo" == @"foo"; 

2)

NSString *myString1 = @"foo"; 
NSString *myString2 = @"foo"; 
myString1 == myString2; 

हालांकि, वहाँ निश्चित रूप से कई बार जहां दो NSString s का उपयोग करके की तुलना नहीं की जा सकता है समानता ऑपरेटर, और [myString1 isEqualToString:myString2] इसके बजाए आवश्यक है। क्या कोई इस पर कुछ प्रकाश डाला सकता है?

उत्तर

155

कारण == काम सूचक तुलना की वजह से है। जब आप @"" का उपयोग करते हुए स्थिर NSString को परिभाषित करते हैं, तो संकलक संदर्भ को विशिष्ट करता है। जब आपके कोड में अन्य स्थानों में समान स्थिरांक परिभाषित किए जाते हैं, तो वे सभी स्मृति में एक ही वास्तविक स्थान को इंगित करेंगे।

NSString *myString1 = @"foo"; 
NSString *myString2 = @"foo"; 
NSString *myString3 = [[NSString alloc] initWithString:@"foo"]; 
NSLog(@"%d", (myString2 == myString3)) //0 
NSLog(@"%d", (myString1 == myString2)); //1 
NSLog(@"%d", [myString1 isEqualToString:myString2]); //1 
NSLog(@"%d", [myString1 isEqualToString:myString3]); //1 
[myString3 release]; 
+6

अधिकांश कंपाइलर 'myString3' को एक अनुकूलक के रूप में स्थिर' 'foo' 'के लिए एक सूचक भी बनाते हैं, इसलिए आम तौर पर, इन तीनों में से सभी चर समान स्मृति स्थान को इंगित करेंगे। यह दोनों जीसीसी और क्लैंग (डिफ़ॉल्ट विकल्पों के साथ) के लिए सच है। इसे संकलित करने का प्रयास करें: http://gist.github.com/578568 – mipadi

+0

और इसलिए मैं एक एनएसएसटींग वैरिएबल को बिल्कुल "" ... "जैसा कैसे कर सकता हूं? कारण मैं पूछता हूं कि मेरे कोड में बी/सी अभी निरंतर @ ".." काम करता है, लेकिन जैसे ही मैं इसे एनएसएसटींग चर के साथ बदलता हूं, यह क्रैश हो जाता है .. [यहां] देखें (http://stackoverflow.com/questions/14462951/ios-sqlite3-statement-coalesce-cause-memory-problems) – abbood

+2

+1, बस जोड़ने के लिए: 'isEqual:' वास्तव में एक पूर्ण स्ट्रिंग तुलना करता है और 'isEqualToString' के समान परिणाम देता है क्योंकि _NSObject प्रोटोकॉल संदर्भ_ और _एनएसएसटींग क्लास रेफरेंस_ स्पष्ट रूप से निर्दिष्ट (क्रमशः) निर्दिष्ट करता है: "यदि दो ऑब्जेक्ट बराबर हैं (' -isEqual: ') द्वारा उनके पास एक ही हैश मान होना चाहिए" और "यदि दो स्ट्रिंग ऑब्जेक्ट बराबर हैं (जैसा कि isEqualToString: विधि द्वारा निर्धारित किया गया है) , उनके पास एक ही हैश मान होना चाहिए। " – Ephemera

6

कोको स्ट्रिंग्स में एनएसएसटींग की isEqualToString: विधि का उपयोग करके तुलना की जाती है।

पॉइंटर तुलना आपके मामले में काम करती है क्योंकि संकलक एक ऑब्जेक्ट को इंगित करने के लिए दो स्ट्रिंग अक्षरों को मर्ज करने के लिए पर्याप्त नरम है। इस बात की कोई गारंटी नहीं है कि दो समान तार एक NSString उदाहरण साझा करते हैं।

+0

क्या आपके पास इसका कोई आधिकारिक संदर्भ है?"इस बात की कोई गारंटी नहीं है कि दो समान तार एक एनएसएसटींग उदाहरण साझा करते हैं।" –

+0

@ user3055655 मुझे संदर्भ की आवश्यकता नहीं है: आप आसानी से कोड लिख सकते हैं जो समान सामग्री वाले दो अलग-अलग 'एनएसएसटींग' उदाहरण बनाता है: '[एनएसएमयूटेबल स्ट्रिंग स्ट्रिंग]! = [एनएसएमयूटेबल स्ट्रिंग स्ट्रिंग]' –

+0

@ user3055655 यदि आपका मतलब है कि मेरा दावा है स्ट्रिंग अक्षर के लिए सच नहीं है: दो बंडलों से शाब्दिक प्रयास करें (जैसे ऐप और उसके परीक्षण बंडल)। –

13

समानता ऑपरेटर == केवल सूचक पतों तुलना:

जब NSString उदाहरणों की तुलना, आप isEqualToString: विधि का उपयोग करना चाहिए। जब आप शाब्दिक @"" वाक्यविन्यास का उपयोग करके दो समान तार बनाते हैं, तो संकलक यह पता लगाएगा कि वे बराबर हैं, और केवल एक बार डेटा संग्रहित करते हैं। इसलिए, दो पॉइंटर्स एक ही स्थान पर इंगित करते हैं। हालांकि, अन्य माध्यमों द्वारा बनाए गए स्ट्रिंग में समान डेटा हो सकता है, फिर भी विभिन्न मेमोरी स्थानों पर संग्रहीत किया जा सकता है। इसलिए, स्ट्रिंग की तुलना करते समय आपको हमेशाisEqual: का उपयोग करना चाहिए।

ध्यान दें कि isEqual: और isEqualToString: हमेशा एक ही मान वापस करते हैं, लेकिन isEqualToString: तेज़ है।

+2

यह भी ध्यान दें कि 'isEqualToString': अपवाद का कारण बन जाएगा यदि पैरामीटर पास किया गया है तो यह शून्य है। तो यदि कोई मौका है कि आप एक नील स्ट्रिंग की तुलना कर रहे हैं, तो आपको या तो पहले एक शून्य जांच करनी चाहिए या 'isEqual: ' –

10

== स्मृति में स्थान की तुलना करता है। ptr == ptr2 यदि वे दोनों एक ही स्मृति स्थान पर इंगित करते हैं। स्ट्रिंग स्थिरांक के साथ काम करने के लिए यह होता है क्योंकि संकलक समान स्ट्रिंग स्थिरांक के लिए एक वास्तविक स्ट्रिंग का उपयोग करता है। यह काम नहीं करेगा यदि आपके पास एक ही सामग्री के साथ चर है, क्योंकि वे विभिन्न स्मृति स्थानों को इंगित करेंगे; इस तरह के मामले में isEqualToString का उपयोग करें।

+0

का उपयोग करना चाहिए, क्या आप इसका मतलब बता सकते हैं कि यह आपके काम के उदाहरण के साथ प्रबुद्ध हो सकता है" यदि आपके पास वैरिएबल हैं सामग्री " –

3

एक उदाहरण का प्रदर्शन कैसे स्ट्रिंग तुलना के लिए एक किराए के रूप में पता तुलना टूट जाएगा:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    NSString *s1 = @"foo"; 
    NSString *s2 = @"foo"; 
    NSString *s3 = [[[NSString alloc] initWithString:@"foo"] autorelease]; 
    NSMutableString *s4 = [NSMutableString stringWithString:@"foobar"]; 
    [s4 replaceOccurrencesOfString:@"bar" 
         withString:@"" 
          options:NSLiteralSearch 
          range:NSMakeRange(0, [s4 length])]; 

    NSLog(@"s1 = %p\n", s1); 
    NSLog(@"s2 = %p\n", s2); 
    NSLog(@"s3 = %p\n", s3); 
    NSLog(@"s4 = %p\n", s4); // distinct from s1 

    NSLog(@"%i", [s1 isEqualToString:s4]); // 1 

    [pool release]; 
0

चेक बाहर इस उदाहरण:

NSString *myString1 = @"foo"; 
NSMutableString *myString2 = [[NSMutableString stringWithString:@"fo"] stringByAppendingString: @"o"]; 

NSLog(@"isEquality: %@", ([myString1 isEqual:myString2][email protected]"+":@"-")); //YES 
NSLog(@"isEqualToStringity: %@", ([myString1 isEqualToString:myString2][email protected]"+":@"-")); //YES 
NSLog(@"==ity: %@", ((myString1 == myString2)[email protected]"+":@"-")); // NO 

तो, संकलक पर कार्रवाई करने के isEqualToString विधि का उपयोग होने की संभावना है NSString और dereference पॉइंटर्स के लिए है, हालांकि यह नहीं था। और पॉइंटर्स अलग हैं, जैसा कि आप देखते हैं।

-1
NSString *str1=[NSString stringWithFormat:@"hello1"]; 
    NSString *str2=[NSString stringWithFormat:@"hello1"]; 
    NSString *str3 = [[NSString alloc] initWithString:@"hello1"]; 




// == compares the pointer but in our example we are taking same string value to different object using @ so it will point to same address so output will be TRUE condition 
    if (str1==str2) { 
     NSLog(@"Both String are equal"); 
    } 
    else{ 
     NSLog(@"Both String not are equal"); 
    } 


    // == compares the pointer but in our example we are taking same string value to different object but we have allocated different string so both object will pount to different address so output will be FALSE condition 
    if (str1==str3) { 

     NSLog(@"Both String are equal"); 
    } 
    else{ 
     NSLog(@"Both String not are equal"); 

    } 


    // compare:= compares the values of objects so output will be TRUE condition 
    if ([str1 compare:str3]== NSOrderedSame) { 
     NSLog(@"Both String are equal"); 

    } 
    else{ 
     NSLog(@"Both String not are equal"); 

    } 


    // isEqual compares the values of objects so output will be TRUE condition 

    if ([str1 isEqual:str2]) { 

     NSLog(@"Both String are equal"); 
    } 
    else{ 
     NSLog(@"Both String not are equal"); 

    } 

    // isEqual compares the values of objects so output will be TRUE condition 

    if ([str1 isEqual:str3]) { 

     NSLog(@"Both String are equal"); 
    } 
    else{ 
     NSLog(@"Both String not are equal"); 

    } 


    // isEqualToString compares the values of objects so output will be TRUE condition 
    if ([str1 isEqualToString:str2]) { 

     NSLog(@"Both String are equal"); 
    } 
    else{ 
     NSLog(@"Both String not are equal"); 

    } 


    // isEqualToString compares the values of objects so output will be TRUE condition 
    if ([str1 isEqualToString:str3]) { 

     NSLog(@"Both String are equal"); 
    } 
    else{ 
     NSLog(@"Both String not are equal"); 

    } 

    // == compares the pointers since we have initialized the same value to first object so the pointer be be same for same value so output will be TRUE condition 
    if ([email protected]"hello1") { 

     NSLog(@"Both String are equal"); 
    } 
    else{ 
     NSLog(@"Both String not are equal"); 

    }