У меня есть свойство ccColor3B в моем классе, которое я хотел бы сохранить с помощью NSCoding. Как я могу это достичь? У NSCoder нет способа, который позволяет это.NSCoding a ccColor3B field
ответ
@Justin правильно, вы должны закодировать с помощью байт, но я думаю, что он над мыслительными вещами:
// encode
ccColor3B input;
[coder encodeBytes:&input length:sizeof(input) forKey:@"color"];
// decode
ccColor3B output;
const uint8_t *bytes = [coder decodeBytesForKey:@"color" returnedLength:NULL];
memcpy(&output, bytes, sizeof(output));
Encode байт, например, так:
const NSUInteger BytesInCCColor = 3U;
const uint8_t bytes[BytesInCCColor] = { color.r, color.g, color.b };
[coder encodeBytes:bytes length:BytesInCCColor forKey:@"color"];
Декодирование:
NSUInteger outLength = 0;
const uint8_t* const bytes =
[coder decodeBytesForKey:@"color" returnedLength:&outLength];
if (NULL == bytes || BytesInCCColor != outLength) {
…uh-oh…
}
else {
color.r = bytes[0];
color.g = bytes[1];
color.b = bytes[2];
}
Я должен downvote это несмотря на то, что работает, потому что он делает это очень опасный стиль. Вы должны использовать sizeof (цвет), а не hardcoded 3. –
@JoeWreschnig я вижу ** ноль ** опасность в этой реализации ... продолжайте и * объясните *, что «очень опасный стиль» для меня. есть веская причина для использования фиксированного числа: 3-компонентная последовательность байтов - это то, что закодировано в моей реализации, а не «цвет». конечно, я оставил расширенную обработку ошибок и управление версиями в OP. педантизм: * ваша * реализация предполагает макеты памяти союзов в реализации при использовании нескольких активных членов; это неуказанное поведение. стандарт не гарантирует, что память элементов будет выровнена или перекрыта. – justin
Опасность - это практика размеров структуры жесткого кодирования, а не использование sizeof (var) (или когда это невозможно, sizeof (type)). Как я уже сказал, в этой реализации нет никакой опасности, потому что это само по себе правильно, но идиома плоха - все, что требуется, - это кому-то поставить «2» вместо «3», и она не разваливается без предупреждения. C действительно гарантирует тип-шлейфы (и iirc четные указатели, но которые часто мешают предупреждениям компилятора) эквивалентных неподписанных/подписанных типов работают так, как я их использую. –
Лучше, чем использование ad-hoc-небезопасных преобразований - это реализовать категорию на NSCoder, которая понимает, как с ней обращаться:
@implementation NSCoder (cocos2d)
- (void)encodeUInt32:(uint32_t)i forKey:(NSString *)key {
union { int32_t s; uint32_t u; } v;
v.u = i;
[self encodeInt32:v.s forKey:key];
}
- (uint32_t)decodeUInt32ForKey:(NSString *)key {
union { int32_t s; uint32_t u; } v;
v.s = [self decodeInt32ForKey:key];
return v.u;
}
- (void)encodeColor3B:(ccColor3B)color forKey:(NSString *)key {
/* Storing 0xFF as the low 8 bits allows us to read/write ccColor3B
and ccColor4B interchangeably. */
uint32_t rgba = (color.r << 24) | (color.g << 16) | (color.b << 8) | 0xFF;
[self encodeUInt32:rgba forKey:key];
}
- (ccColor3B)decodeColor3BForKey:(NSString *)key {
ccColor3B c;
uint32_t rgba = [self decodeUInt32ForKey:key];
c.r = rgba >> 24;
c.g = rgba >> 16;
c.b = rgba >> 8;
return c;
}
@end
Тогда вы можете просто сделать:
self.color = [decoder decodeColor3BForKey:@"color"];
и
[encoder encodeColor3B:self.color forKey:@"color"];
@RichardJRossIII хорошо, я показывал иллюстративный пример, пытаясь избежать переносимости и тома «ABI gotchas», который должен сопровождать байт-копирующие структуры при сериализации :) – justin