3

我有一个覆盖 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

当我在数组中找到人时,它不会调用 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");

这是输出:

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

你知道这是为什么吗?

4

3 回答 3

7

尽管 Apple 的文档说它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]);

在 People 的 isEqual 方法中:

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

输出:

A.isEqual called C
A.isEqual called C
find A 2
于 2013-04-10T12:00:51.403 回答
4

如果a == b,那么b == a

或者,就 Objective-C 而言,如果[a isEqual:b], then也[b isEqual:a]必须为 true

-isEqual:违反了该规则。

如何NSArray使用这些isEqual:方法完全是一个实现细节,除此之外isEqual:将用于包含测试

于 2013-04-10T17:15:26.517 回答
1

As kovpas's answer, I change isEqual method to adapt with the new idea:

#import "People.h"

@implementation People
@synthesize name = _name, age = _age;


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

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

@end

Then add desired String to compare into a people

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

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

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

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

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

It will work like a charm :)

2013-04-11 10:28:55.659 runone[1029:303] A.isEqual called
2013-04-11 10:28:55.659 runone[1029:303] find A 0 
于 2013-04-11T03:41:54.850 回答