NSValue/NSNumber создание заданной кодировки /objCType
Я пытаюсь синхронизировать объекты через GameCenter, получая доступ к их значениям с KVC с обеих сторон. Установка числовых значений с помощью setValue:forKey:
требует от них быть NSNumber
объекты.NSValue initWithBytes:objCType:
дает мне NSValue
объекты, даже проходящие кодировки для int, float и тому подобное.
У вас, ребята, есть лучшее решение вместо проверки кодировки вручную?
- (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];
}
Если это путь, это NSNumber
единственный NSValue
подкласс мне нужно позаботиться о KVC?
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];
}