使用NSArray containObject:方法比较对象


问题是这么来的…

我写了一个类方法返回了一个NSArray


 +(NSArray *)validOperator
{
    return @[@"+", @"-", @"*", @"/", @"%", @"(", @")", @"="];
}

然后我想判断某个操作符是否在上面返回的数组中


 -(BOOL)isOperator:(NSString *)ch
{
    if ([[Calculate validOperator] containsObject:ch]) {
        return YES;
    }else
        return NO;
}

这时候问题就来了,即使ch在数组中,方法返回的也是NO。

然后我在网上搜索了一下…

然后我在网上搜了一下,大概找到问题的原因了。
苹果的文档对 [NSArray containsObject:] 是这么说的:

This method determines whether anObject is present in the receiver by sending an isEqual: message to each of the receiver’s objects (and passing anObject as the parameter to each isEqual: message).

所以问题应该是比较的是对象的引用(地址?),而不是对象的值。

找到原因了下面就要解决问题了

看到 StackOverflow 上这个人遇到的问题跟我差不多,他采纳的答案中提到了两种方法,还给了一个关于实现-isEqual:和-hash重载的 问题链接

you will either need to send [collection containsObject:] an instance of a variable it contains (e.g. A, B, or C), or you will need to override the [NSObject isEqual:] method in your Fruit class.

最后问题来了

  1. 请问上面那个回答中提到的第一种方法可行吗?我发送的ch原本定义的是char,然后使用了stringWithUTF8String:转化成NSString。
  2. 关于实现-isEqual:和-hash的重载,我看了上面提到的问题链接,有-isEqual:的重载模版,但是-hash的重载还是没说清楚的样子,请问能不能给个有关的例子可以学习一下。

刚接触iOS开发,希望各位路过的好心人能解答一下,万分感谢!

补充1

对了,我也考虑过不使用containObject:的,就是用NSString的isEqualToString方法,把数组里的元素拿出来。


 -(BOOL)isOperator:(NSString *)ch
{
    NSArray *optrArray = [Calculate validOperator];  
    for (NSString *optr in optrArray) {
    NSLog(@"optr:%@ ,ch:%@", optr,ch);
    if ([optr isEqualToString:ch]) {
        return YES;
    }
}
    return NO;
}

还是不行(╥﹏╥)

补充2

好吧,我发现我的问题在哪里了,不是containObject:的问题,我要比较的还是NSString的两个对象,所以问题是传递的变量ch上。我发现,如果直接传一个@"+",不管使用containObject:还是用isEqualToString的方法都没问题,但是按下面的代码就有问题了:


 //inputString是从textfield获取的一个NSString
for (int i = 0; i < [inputString length]; i++) {   
    char ch = [inputString characterAtIndex:i];
    NSString *str = [NSString stringWithUTF8String:&ch];
    if (![self isOperator:str]) {
    ……
    }
    ……
}

痛定思痛,追根溯源,找到了症结:


 char ch = [inputString characterAtIndex:i];
NSString *str = [NSString stringWithUTF8String:&ch];

对,问题就在stringWithUTF8String:这个方法上,暂时先把这个方法放放,把它改成stringWithFormat:的方法如下:


 NSString *str = [NSString stringWithFormat:@"%c", ch];

然后,世界终于清静了……containObject:和isEqualToString应该可以随便用,都是NSString没什么好害羞的。 今天太晚了,明天等程序写完了再研究下用stringWithUTF8String:是怎么样出错的。 至于stringWithUTF8String:,因为它会在str末尾会包含"\n"= =

xcode ios objective-c

镜JING 11 years, 6 months ago

你传过去的参数类型对吗?

zhouxin answered 11 years, 6 months ago

Your Answer