【问题标题】:Duplicated custom object in NSSetNSSet 中重复的自定义对象
【发布时间】:2013-10-25 02:15:16
【问题描述】:

我对 Objective-C 中的 NSMutableSet 有一些问题。 我了解到 NSSet 会比较两个对象的哈希码来决定它们是否相同。 问题是,我自己实现了一个类,它是NSObject 的子类。该类中有一个属性NSString *name。我想要做的是当这个自定义类的实例具有相同的变量值 "name" 时,它们应该是相同的,并且在添加到 NSMutableSet 时不应重复这样的相同类。

所以我重写了- (NSUInteger)hash 函数,调试显示它为我的两个实例obj1, obj2 (obj1.name == obj2.name) 返回相同的哈希值。但是当我将 obj1、obj2 添加到 NSMutableSet 时,NSMutableSet 中仍然包含 obj1、obj2。

我尝试了两个具有相同值的NSString,然后将它们添加到NSMutableSet,集合将只有一个NSString

有什么解决办法?感谢您的帮助!

自定义类: 对象.h:

#import <Foundation/Foundation.h>

@interface Object : NSObject

@property (retain) NSString *name;

@end

对象.m

@implementation Object
@synthesize name;

-(BOOL)isEqualTo:(id)obj {
    return [self.name isEqualToString:[(Object *)obj name]] ? true : false;
}

- (NSUInteger)hash {
    return [[self name] hash];

}
@end

和主要的:

#import <Foundation/Foundation.h>
#import "Object.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Object *obj1 = [[Object alloc]init];
        Object *obj2 = [[Object alloc]init];
        obj1.name = @"test";
        obj2.name = @"test";
        NSMutableSet *set = [[NSMutableSet alloc] initWithObjects:obj1, obj2, nil];
        NSLog(@"%d", [obj1 isEqualTo:obj2]);
        NSLog(@"%ld", [set count]);
    }
    return 0;
}

【问题讨论】:

  • 你是否也覆盖了isEqual:
  • 您能否展示您对hashisEqual 的实现以及如何将对象添加到集合中?
  • 您实施了错误的方法。 isEqual:isEqualTo: 不同 您也不能假设您正在测试相等性的对象甚至 具有 一个名为 name 的属性。你应该阅读Mike Ash's post about equality and hashing

标签: objective-c cocoa hash nsset


【解决方案1】:

你必须实现isEqual:,而不是实现isEqualTo:

- (BOOL)isEqual:(id)object {
    return [object isKindOfClass:[MyObject class]] &&
           [self.name isEqual:[(MyObject *)object name]];
}

如果self.nameobject.name 都是nil,这将(可能错误地)返回NO。如果你想返回YES,如果两个属性都是nil,你应该使用

- (BOOL)isEqual:(id)object {
    if ([object isKindOfClass:[MyObject class]]) {
        return (!self.name && ![(MyObject *)object name]) ||
        [self.name isEqual:[(MyObject *)object name]];
    }
    return NO;
}

【讨论】:

  • 使用[self class] 会导致[a isEqual:b] != [b isEqual:a],我认为这是不应该的(当ba 的子类而不覆盖isEqual: 时)。
  • 更具体地说,如果 ab 类的子类的实例,[a isEqual:b] 将返回 NO(因为 b 不是 a 类) 和[b isEqual:a] 将返回YES,因为ab 的类。 (使用[self class]时)
  • 不用担心。我还更新了关于 name 属性为零的答案。
猜你喜欢
  • 1970-01-01
  • 2020-07-07
  • 2016-06-17
  • 2020-06-28
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
相关资源
最近更新 更多