我有一个具有C数组属性的Objective-C类
我想用NSCoding序列化该属性。
@interface TestClass : NSObject <NSCoding>
@property (nonatomic) int* intArray;
@end
@implementation TestClass
-(instancetype)init
{
self = [super init];
if (self) {
_intArray = (int *)malloc(sizeof(int) * 5);
for (int i = 0; i < 5; i++) {
_intArray[i] = 0;
}
}
return self;
}
-(void)dealloc
{
free(_intArray);
}
-(instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
//???
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder
{
//???
}
@end
我应该写什么? 谢谢。
修改
谢谢你的回答
但是我应该使用decodeArrayOfObjCType:count:at:或NSData?
如果我不知道数组的数量,我不能使用decodeArrayOfObjCType:count:at:method?
-(instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
_itemCount = [coder decodeIntForKey:kItemCount];
_intArray = (int *)malloc(sizeof(int) * _itemCount);
[coder decodeArrayOfObjCType:@encode(int) count:_itemCount at:_intArray];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeInt:_itemCount forKey:kItemCount];
[coder encodeArrayOfObjCType:@encode(int) count:_itemCount at:_intArray];
}
或
-(instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
_itemCount = [coder decodeIntForKey:kItemCount];
NSData *data = [coder decodeObjectForKey:kIntArray];
if (data) {
NSUInteger length = [data length];
_intArray = (int *)malloc(length);
[data getBytes:_intArray length:length];
}
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeInt:_itemCount forKey:kItemCount];
if (_intArray) {
NSData *data = [NSData dataWithBytes:_intArray length:sizeof(int) * _itemCount];
[coder encodeObject:data forKey:kIntArray];
}
}
谢谢。
答案 0 :(得分:5)
如果您在解码时不知道阵列中有多少个值,那么您可能想要使用NSData
。因此,您可能有两个属性,一个用于intData
,另一个用于数组中count
项:
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
NSData *data = [coder decodeObjectForKey:kIntArrayKey];
if (data) {
NSUInteger length = [data length];
self.count = length / sizeof(int);
self.intArray = (int *)malloc(length);
[data getBytes:_intArray length:length];
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
if (_intArray) {
NSData *data = [NSData dataWithBytesNoCopy:self.intArray length:sizeof(int) * self.count freeWhenDone:NO];
[coder encodeObject:data forKey:kIntArrayKey];
}
}
或者,如果您不想使用NSData
,则可以使用encodeBytes:length:forKey:
:
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
NSUInteger length;
const uint8_t *bytes = [coder decodeBytesForKey:kIntArrayKey returnedLength:&length];
if (bytes) {
self.count = length / sizeof(int);
self.intArray = (int *)malloc(length);
memcpy(_intArray, bytes, length);
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
if (_intArray) {
[coder encodeBytes:(void *)self.intArray length:sizeof(int) * self.count forKey:kIntArrayKey];
}
}
档案和序列化编程指南的Encoding and Decoding C Data Types概述了一些其他注意事项:
简单类型的数组
如果要编码一个字节数组,可以使用提供的方法来执行此操作。
对于其他算术类型,请使用数组创建
NSData
对象。请注意,在这种情况下,处理平台字节序问题是您的责任。平台字节序可以通过两种通用方式处理。第一种技术是将数组的元素(或者更确切地说,数组的临时副本)转换为规范的字节序,大或小,一次一个,具有在通用二进制编程指南中交换字节中讨论的函数,第二种版本(另请参阅Foundation Functions Reference中的“字节排序”)并将结果作为缓冲区提供给NSData
。 (或者,您可以使用encodeBytes:length:forKey:
直接写入字节。)在解码时,您必须反转该过程,从大或小端规范形式转换为当前主机表示。另一种技术是按原样使用数组并记录单独的键控值(可能是布尔值),即创建存档时主机的字节顺序。在解码期间,读取endian键并将其与当前主机的字节序进行比较,并仅在不同时交换值。或者,您可以将每个数组元素分别归档为其本机类型,可能使用受数组语法启发的键名称,如
“theArray[0]”
,“theArray[1]”
等。这不是一种非常有效的技术,但您可以忽略端点问题。
答案 1 :(得分:4)
-(instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
_intArray = (int *)malloc(sizeof(int) * 5);
[coder decodeArrayOfObjCType:@encode(int) count:5 at:_intArray];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder {
[coder encodeArrayOfObjCType:@encode(int) count:5 at:_intArray];
}