开发者

NSSet with NSStrings containstObject not return YES when it should

开发者 https://www.devze.com 2023-03-27 09:24 出处:网络
I\'m loading a dictionary (list of word, not the class) into a NSSet as NSStrings. I then repeatedly send this set the message -containsObject:someNSString. But it always returns false. I wrote some c

I'm loading a dictionary (list of word, not the class) into a NSSet as NSStrings. I then repeatedly send this set the message -containsObject:someNSString. But it always returns false. I wrote some code to test it:

NSLog(@"Random from dictionary: %@", [dictionary anyObject]);
NSString *test = [NSString stringWithFormat:@"BEMIRED"];
NSLog(@"To match this word: %@", test);
if ([dictionary containsObject:test])
    NSLog(@"YES!");

In t开发者_高级运维he log I get the following:

Random from dictionary: BEMIRED
To match this word: BEMIRED

(I'm missing the "YES!")

When I try using CFShow(dictionary) I can see that it actually contains Strings and that everything. An example:

0 : <CFString 0xc3bd810 [0x1386400]>{contents = "BEMIRED"}
3 : <CFString 0xdf96ef0 [0x1386400]>{contents = "SUBJECTIFIED"}

Can anyone please help me here? Thanks!


NSSet uses isEqual: to test for object equality, which NSString overrides to perform a string comparison as you would expect. The follow unit test passes:

- (void)testSetStrings
{
    NSSet *set = [NSSet setWithObject:@"String 1"];

    // I've used the UTF8 initializer to avoid any cleverness from reusing objects
    NSString *string1 = [[[NSString alloc] initWithUTF8String:"String 1"] autorelease];

    // Test the references/pointers are not the same
    STAssertTrue([set anyObject] != string1, nil);

    STAssertTrue([set containsObject:string1], nil);
}

We can see the two strings have different pointer values, but the set still returns YES for the containsObject: call.

So I would guess your strings are not in fact equal. I would check for hidden whitespace or other similar issues.


The -[NSSet containsObject:] seems to check for the pointer value only (the documentation is very lacking for that method), not for object equality. So you need to use -[NSSet member:] instead, which uses isEqual: to check whether an object that is considered to be equal is in your set.

if ([dictionary member:test])
    NSLog(@"YES!");

Edit: Actually it seems that containsObject: does use isEqual: as well. They only seem to differ in what they return (containsObject: returns a BOOL while member: returns id). I'm letting this answer stay for documentation purposes.


Ok so I solved the problem and it had nothing to do with the containsObject method. As I commented i used Dave DeLongs DDFileReader found here: Dave DeLongs DDFileReader

So by using CFShow on the entire dictionary I noticed that every word had a new line at the end of it. So instead of the -readLine method i used the -readTrimmedLine (bot methods in above mentioned file reader). This solved the problem for me.

For future forum visitors I'd like to draw attention to the discussion DarkDust and zoul had about -containsObject and -member (both methods of NSSet) which it turns out both uses the -isEqual method.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号