如何从类和选择器创建哈希? (目标c)

时间:2013-01-20 19:47:00

标签: objective-c hash

我有一个字典,它使用类名和选择器的组合作为键来存储对象。我正在使用以下函数来计算哈希:

+(NSString*) getKeyForClass:(Class) clazz andSelector:(SEL) selector {
    return [NSString stringWithFormat:@"%@_%@",NSStringFromClass(clazz), NSStringFromSelector(selector)];
}

在运行探查器时,我发现此功能是计算的瓶颈。是否有更好(=更有效)的方法从类和选择器创建键?

2 个答案:

答案 0 :(得分:3)

一些替代方案。

继续使用字符串作为键,但要更快地执行:

使用字符串比你真正需要的更重要,但它至少是简单的。

使用-[NSString stringByAppendingString]会更快。解析格式字符串是很多工作。

return [[NSStringFromClass(clazz) stringByAppendingString:@"_"] stringByAppendingString:NSStringFromSelector(selector)];

最好使用单个NSMutableString而不是制作中间字符串。简介并查看。

NSMutableString* result = [NSStringFromClass(clazz) mutableCopy];
[result appendString:@"_"];
[result appendString:NSStringFromSelector(selector)];
return result;

使用自定义对象作为键:

您可以将自定义对象设置为引用类和选择器的键。在其上实施NSCopying-isEqual:以及-hash,以便您可以将其用作字典中的键。

@interface MyKey : NSObject <NSCopying>
{
    Class _clazz;
    SEL _selector;
}

- (id)initWithClass:(Class)clazz andSelector:(SEL)selector;

@end

@implementation MyKey

- (id)initWithClass:(Class)clazz andSelector:(SEL)selector
{
    if ((self = [super init])) {
        _clazz = clazz;
        _selector = selector;
    }
    return self;
}

- (id)copyWithZone:(NSZone*)zone
{
    return self; // this object is immutable, so no need to actually copy it
}

- (BOOL)isEqual:(id)other
{
    if ([other isKindOfClass:[MyKey class]]) {
        MyKey* otherKey = (MyKey*)other;
        return _clazz == otherKey->_clazz && _selector == otherKey->_selector;
    } else {
        return NO;
    }
}

// Hash combining method from http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html
#define NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger))
#define NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (NSUINT_BIT - howmuch)))

- (NSUInteger)hash
{
    return NSUINTROTATE([_clazz hash], NSUINT_BIT / 2) ^ (NSUInteger)_selector;
}

@end

+ (MyKey*)keyForClass:(Class)clazz andSelector:(SEL)selector
{
    return [[MyKey alloc] initWithClass:clazz andSelector:selector];
}

消灭中间人:

如果您永远不需要从关键对象中提取类和选择器,那么您可以使用上面计算的哈希值,存储在NSNumber中。

// Hash combining method from http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html
#define NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger))
#define NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (NSUINT_BIT - howmuch)))

+ (NSNumber*)keyForClass:(Class)clazz andSelector:(SEL)selector
{
    NSUInteger hash = NSUINTROTATE([clazz hash], NSUINT_BIT / 2) ^ (NSUInteger)selector;
    return [NSNumber numberWithUnsignedInteger:hash];
}

答案 1 :(得分:0)

SEL本身是独一无二的;您可以使用NSValue并将其包装:

[NSValue valueWithBytes:&selector objCType:@encode(SEL)];