我如何使用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;
}
答案 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没有任何方法来处理无符号类型。我想不出这会如何导致任何数据丢失,但它需要一些丑陋的演员,加上它只是感觉很脏。
如果要坚持使用无符号类型,最简单的方法是使用最大可用类型({{{htonl
和ntohl
)对原始字节进行编码(最好采用网络字节顺序) 1}})使用unsigned long long
和encodeBytes: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