1

我正在尝试通过 GameCenter 同步对象,并在两侧使用 KVC 访问它们的值。设置数值 usingsetValue:forKey:要求它们是NSNumber对象。
NSValue initWithBytes:objCType:给我对象,甚至传递intfloatNSValue的编码。

你们有更好的解决方案而不是手动检查编码吗?

- (NSValue*)smartValueWithBytes:(void*)value objCType:(const char*)type
{
    if (0 == strcmp(type, @encode(int)))
    {
        int tmp;
        memcpy(&tmp, value, sizeof(tmp));
        return [NSNumber numberWithInt:tmp];
    }
    if (0 == strcmp(type, @encode(BOOL)))
    {
        BOOL tmp;
        memcpy(&tmp, value, sizeof(tmp));
        return [NSNumber numberWithBool:tmp];
    }
    //etc...
    return [NSValue valueWithBytes:value objCType:type];
}

如果这是要走的路,那么我需要为 KVC 处理NSNumber的唯一子类是什么?NSValue

4

1 回答 1

1

这是我对这个问题的解决方案,只对浮点值进行了专门化(因为它们很奇怪!)

NSValue *safeValueForKVC(const void *input, const char *type)
{
    const char numericEncodings[] = { 
        'c',
        'i', 
        's', 
        'l', 
        'q', 
        'C', 
        'I',
        'S',
        'L',
        'Q',
        'f',
        'd',
    };
    const size_t sizeEncodings[] = {
        sizeof(char),
        sizeof(int),
        sizeof(short),
        sizeof(long),
        sizeof(long long),
        sizeof(unsigned char),
        sizeof(unsigned int),
        sizeof(unsigned short),
        sizeof(unsigned long),
        sizeof(unsigned long long),
        sizeof(float),
        sizeof(double),
    };

    int typeLen = strlen(type);

    if (typeLen == 1)
    {
        for (int i = 0; i < sizeof(numericEncodings); i++)
        {
            if (type[0] == numericEncodings[i])
            {
                // we have a numeric type, now do something with it
                if (i == 10)
                {
                    // floating-point value
                    float fValue = 0;

                    memcpy(&fValue, input, sizeEncodings[i]);

                    return [NSNumber numberWithFloat:fValue];
                }
                if (i == 11)
                {
                    // double value
                    double dValue = 0;

                    memcpy(&dValue, input, sizeEncodings[i]);

                    return [NSNumber numberWithDouble:dValue];
                }

                // standard numeric value, simply padding with false bits should work for any reasonable integer represetntation
                long long value = 0;
                memcpy(&value, input, sizeEncodings[i]);

                return [NSNumber numberWithLongLong:value];
            }
        }
    }

    return [[NSValue alloc] initWithBytes:input objCType:type];
}
于 2012-07-19T02:08:02.893 回答