如何使用NSCoding存储NSUInteger?

时间:2010-09-15 06:01:30

标签: objective-c cocoa

我如何使用NSUInteger协议存储NSCoding,因为NSCoder上的方法与-encodeUnsignedInteger:(NSUInteger)anInt forKey:(NSString *)aKey类似,只有NSInteger

以下是有效的,但这是最好的方法吗?这确实会不必要地创建对象。

@interface MYObject : NSObject <NSCoding> {
    NSUInteger count;
}  

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:[NSNumber numberWithUnsignedInteger:count] forKey:@"count"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super init];
    if (self != nil) {
        count = [[decoder decodeObjectForKey:@"count"] unsignedIntegerValue];
    }
    return self;
}

4 个答案:

答案 0 :(得分:26)

NSNumber有很多方法可以存储/检索不同大小和签名的类型。这是最简单的解决方案,不像其他答案那样需要任何字节管理。

以下是根据NSNumber上的Apple文档的类型:​​

+ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value
- (NSUInteger)unsignedIntegerValue

是的,您的代码示例是对NSUInteger进行编码/解码的最佳方式。我建议使用常量作为键值,这样你就不会输入错误并引入存档错误。

static NSString * const kCountKey = @"CountKey";

@interface MyObject : NSObject <NSCoding> {
    NSUInteger count;
}  

@end

@implementation MyObject

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:[NSNumber numberWithUnsignedInteger:count] forKey:kCountKey];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super init];
    if (self != nil) {
        count = [[decoder decodeObjectForKey:kCountKey] unsignedIntegerValue];
    }
    return self;
}
@end

答案 1 :(得分:12)

问题是NSUInteger的大小可能与unsigned int的大小不同。在许多(如果不是最多的话)Mac OS X机器上,NSUInteger将是unsigned long,这将是两倍大。另一方面,键控归档器应该没有问题地处理它,因为它构建了一个字典。

更复杂的是,NSCoder没有任何方法来处理无符号类型。我想不出这会如何导致任何数据丢失,但它需要一些丑陋的演员,加上它只是感觉很脏。

如果要坚持使用无符号类型,最简单的方法是使用最大可用类型({{{htonlntohl)对原始字节进行编码(最好采用网络字节顺序) 1}})使用unsigned long longencodeBytes:length:forKey:。为了最大限度地提高安全性,您应该检查解码后的长度并投射指针(或使用联合)来提取正确大小的类型。

这样做的缺点是该值将在输出中表示为数据,而不是整数。这主要是因为有人决定读取存档的原始plist数据而不是像你那样使用键控的unarchiver,甚至只读它们。可能重要的其他情况是,Apple(或您)是否应该切换到具有更大整数类型的体系结构,类型的位大小不是2的幂(至少有一个旧平台,其中一个单词是24位),或具有不寻常布局的类型(不是大端或小端)。

至于您的NSNumber解决方案:您可能想要在属性列表编辑器中打开存档并查看其发出的内容。如果输出包含整数元素,那么它与使用decodeBytesForKey:returnedLength:相同。如果输出包含数据元素,那么它与我上面提到的解决方案相同。要彻底,您应该检查您支持的每个体系结构的输出。

答案 2 :(得分:2)

这是最好的方法。它看起来似乎是不必要的工作,但是没有其他可用的类型可以代表NSUInteger可以容纳的整个值范围。

答案 3 :(得分:-1)

你想要使用NSCoder的

encodeInt:ForKey:

decodeIntForKey:

方法。所以,在你的情况下你需要:

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeInt:count forKey:@"count"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super init];
    if (self != nil) {
        count = [decoder decodeIntForKey:@"count"];
    }
    return self;
}

希望有帮助,还有更多编码“编码”方法,看看NSCoder的文档:D