我正在尝试创建一个有序字典作为NSMutableDictionary的子类。我使用this article作为指南,但我尝试通过阅读NSDictionary
和NSMutableDictionary
的文档来执行自己的实现,这导致我的做法与文章略有不同。也就是说,setObject:forKey:
的密钥的参数应该是id<NSCopying>
(根据文档),它不在文章中。
问题是当我在setObject:forKey:
中设置一些值时,我无法可靠地检索它 - 它有时会找到该键的对象,有时则不会。我没有在我的应用程序中的任何地方使用块或线程或GCD,所以我不明白它可能是如何随机行为。
这是我的代码:
// BBOrderedDictionary.h
@interface BBOrderedDictionary : NSMutableDictionary
@end
// BBOrderedDictionary.m
@interface BBOrderedDictionary ()
@property (nonatomic, strong) NSMutableArray* array;
@property (nonatomic, strong) NSMutableDictionary* dictionary;
@end
@implementation BBOrderedDictionary
-(instancetype)init
{
return [self initWithCapacity:0];
}
-(instancetype)initWithCapacity:(NSUInteger)numItems
{
self = [super init];
if (self) {
self.array = [NSMutableArray array];
self.dictionary = [NSMutableDictionary dictionary];
}
return self;
}
# pragma mark - Primitive Methods
// NSMutableDictionary Primitive Methods
-(void)setObject:(id)anObject forKey:(id<NSCopying>)aKey
{
if (![self.dictionary objectForKey:aKey]) {
[self.array addObject:aKey];
}
[self.dictionary setObject:anObject forKey:aKey];
}
-(void)removeObjectForKey:(id)aKey
{
[self.dictionary removeObjectForKey:aKey];
[self.array removeObject:aKey];
}
// NSDictionary Primitive Methods
-(NSUInteger)count
{
return [self.dictionary count];
}
-(id)objectForKey:(id)aKey
{
return [self.dictionary objectForKey:aKey];
}
-(NSEnumerator *)keyEnumerator
{
return [self.array objectEnumerator];
}
#pragma mark - Other
-(NSArray *)allKeys
{
return self.array;
}
@end
我应该提到我的密钥也是一个自定义对象,它符合NSCopying
并实现isEqual:
。它可以作为NSMutableDictionary
中的一键使用。
当我在objectForKey:
中设置断点时,我可以验证内部字典确实包含了我放入的所有内容,但是(从将日志放入我的密钥类的isEqual:
方法中),它不会检查所有键与key参数的相等性。有什么想法吗?
答案 0 :(得分:3)
NSDictionary不是单个类,而是类集群。 NSDictionary是实现公共接口功能的不同私有类系列的公共接口。如果要子类化类,则必须实现支持公共接口的所有基本方法。请参阅“子类注释”下的NSDictionary上的Xcode文档。这会告诉你你需要做什么,虽然我建议不要这样做。
类集群通常会在很难模仿的情况下进行大量专门的优化。通常最好创建一个在内部管理NSDictionary的自定义对象,并提供一些与字典类相同的方法(“has-a”关系而不是“is-a”关系。有时你可以创建一个要添加的类别虽然您不能覆盖类别中基类的方法,但是这些类之一的功能。
答案 1 :(得分:2)
每当您实现自定义类并实施isEqual:
方法时,您还必须实现hash
方法。有关详细信息,请参阅NSObject
的文档。
如果这两种方法没有正确地协同工作,那么在任何类型的字典或集合中使用该对象(基本上是任何类型的哈希映射),那么事情将无法正常工作。
请注意,为YES
返回isEqual:
的两个对象必须为hash
返回相同的值(这不是默认值)。但是,两个不相等的对象(基于isEqual:
)可能具有或不具有相同的hash
值。
理论上,你可以简单地为每个对象的1
返回hash
,但事情会起作用,但这会使字典和这些对象的集合工作效率非常低。因此,尝试对不等对象返回不同的hash
值。