且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用NSCoding存储NSUInteger?

更新时间:2023-09-24 12:22:46

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

The problem is that NSUInteger may not be the same size as an unsigned int. On many (if not most by now) Mac OS X machines, NSUInteger will be an unsigned long, which will be twice as big. On the other hand, a keyed archiver should handle that without a problem, since it builds a dictionary.

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

Further complicating matters is the fact that NSCoder doesn't have any methods to deal with unsigned types. I can't think of how this would cause any data loss, but it would require some ugly casts, plus it just feels dirty.

如果你想坚持一个无符号类型,最简单的方法是对原始字节进行编码(***使用 htonl ntohl 使用 encodeBytes:length:forKey:在最大类型( unsigned long long decodeBytesForKey:returnedLength:。为了最大程度的安全,你应该检查你解码的长度,并转换指针(或使用联合)来提取正确大小的类型。

If you want to insist upon an unsigned type, the simplest way would be to encode the raw bytes (preferably in network byte order using htonl and ntohl) in the largest type available (unsigned long long) using encodeBytes:length:forKey: and decodeBytesForKey:returnedLength:. For maximum safety, you should check the length of what you decoded and cast the pointer (or use a union) to extract the correct-sized type.

是该值将在输出中表示为数据,而不是整数。这主要是有关的,只有当有人决定读入原始plist数据为您的档案,而不是像你一样使用键控unarchiver,甚至只有他们。其他情况下,如果苹果(或你)应该切换到一个具有更大的整数类型的架构,类型的位大小不是一个二的幂(有至少一个旧平台,一个字是24位)或具有不寻常布局的类型(不大或小端序)。

The drawback of this is that the value will be represented in the output as data, not an integer. This mainly matters only if somebody decides to read in the raw plist data for your archive instead of using the keyed unarchiver like you do, and even then only to them. The other cases where it might matter is if Apple (or you) should ever switch to an architecture that has even larger integer types, types whose size in bits is not a power of two (there's at least one old platform where a word was 24 bits), or types with an unusual layout (not big- or little-endian).

对于您的NSNumber解决方案:您可能想要破解列表编辑器,看看它发出了什么。如果输出包含整数元素,则它与使用 encodeInteger:forKey:相同。如果输出包含数据元素,那么它与上面提到的解决方案相同。要彻底,您应该检查您支持的每个架构的输出。

As for your NSNumber solution: You might want to crack open your archive in Property List Editor and see what it emitted. If the output contains an integer element, then it's the same as using encodeInteger:forKey:. If the output contains a data element, then it's the same as the solution I mentioned above. To be thorough, you should check the output from every architecture you support.