iOS - NSArray indexOfObject不调用自定义的isEqual

tha*_*h84 3 objective-c ios

我有一个覆盖isEqual方法的人类:

#import "People.h"

@implementation People
@synthesize name = _name;


-(BOOL)isEqual:(id)object {
    NSLog(@"A.isEqual called");

    if ([object isKindOfClass:[NSString class]]) {
        NSString *name = object;
        return [self.name isEqualToString:name];
    }
    return [super isEqual:object];
}

@end
Run Code Online (Sandbox Code Playgroud)

当我在数组中找到人时,它不会调用isEqual方法:

People* p1 = [People new];
        p1.name = @"A";

        People* p2 = [People new];
        p2.name = @"B";

        NSArray* peopleArray = [NSArray arrayWithObjects:p1, p2, nil];

        NSLog(@"find A %ld", [peopleArray indexOfObject:@"A"]);

        NSLog(@"isEqual A -> %@", [p1 isEqual:@"A"] ? @"Yes" : @"No");
Run Code Online (Sandbox Code Playgroud)

这是输出:

2013-04-10 18:15:47.988 runone[6273:303] find A 9223372036854775807
2013-04-10 18:15:47.988 runone[6273:303] A.isEqual called
2013-04-10 18:15:47.989 runone[6273:303] isEqual A -> Yes
Run Code Online (Sandbox Code Playgroud)

你知道为什么吗?

kov*_*pas 7

尽管苹果的文档isEqual:在阵列发送到每一个对象,它周围的其他方法-发送isEqual:到您正在搜索的对象.

因为它被认为[a isEqual:b] == [b isEqual:a],在大多数情况下它不应该有任何区别,但在你的情况下它会产生.

这是一个例子:

People* p1 = [People new];
p1.name = @"A";

People* p2 = [People new];
p2.name = @"B";

People* p3 = [People new];
p3.name = @"C";

NSArray* peopleArray = [NSArray arrayWithObjects:p1, p2, p3, nil];

NSLog(@"find A %ld", (unsigned long)[peopleArray indexOfObject:p3]);
Run Code Online (Sandbox Code Playgroud)

在People's isEqual方法中:

-(BOOL)isEqual:(id)object
{
    NSLog(@"A.isEqual called %@", [self name]);
    ...
}
Run Code Online (Sandbox Code Playgroud)

输出:

A.isEqual called C
A.isEqual called C
find A 2
Run Code Online (Sandbox Code Playgroud)

  • 这是对的.数组的实现将调用NSString的isEqual:方法,传入每个Person.这将始终返回NO,因为它们是不同的类型.因此,People和NSString的相等性不对称.如果定义isEqual:,还需要定义-hash,即使NSArray当前没有调用它也是如此. (3认同)