如何将 NSValue 转换为 NSData 并返回?
A 有许多 NSValue
(通过 KVC valueForKey
获得),我需要将其附加到 NSData
对象以便通过网络发送它使用游戏中心。显然,我还需要将 NSValue
从 NSData
转换回更多 KVC (setValue:forKey:
)。
我不知道每个 NSValue
的确切类型,因此我仅限于使用 NSValue
和 NSData
提供的接口。我应该提到 NSValue 从来都不是指针类型。
我很惊讶没有 [NSData dataWithValue:value]
,也没有 [value dataWithEncoding:]
或类似的东西。但也许我是盲目的,没有看到明显的选择。我考虑过使用 getValue: 将值复制到 void* 缓冲区中,但是除了使用 objCType 之外,我应该如何确定缓冲区长度code> 并将其与所有可能的类型进行比较?
我该怎么办?
注意: NSKeyedArchiver
是不可能的,因为它的效率非常低。 4 字节浮点数归档到 142 字节 NSData
,8 字节 CGPoint
归档到 NSData
时使用 260 字节。将发送的数据量保持在最低限度对于我正在做的事情至关重要。
A have a number of NSValue
(obtained via KVC valueForKey
) that I need to append to an NSData
object in order to send it over the network using Game Center. Obviously I will also need to convert the NSValue
back from NSData
for more KVC (setValue:forKey:
).
I don't know the exact type of each NSValue
, so I'm limited to using the interfaces provided by NSValue
and NSData
. I should mention that the NSValue
are never pointer types.
I'm surprised that there's no [NSData dataWithValue:value]
and neither something like [value dataWithEncoding:]
or similar. But maybe I'm blind and not seeing the obvious choice. I thought about using getValue:
to copy the value into a void*
buffer, but how am I supposed to determine the buffer length other than by using objCType
and comparing that with all possible types?
How should I go about this?
NOTE:NSKeyedArchiver
is out of the question because it is terribly inefficient. A 4 Byte float is archived to a 142 Bytes NSData
, a 8 Byte CGPoint
uses 260 Bytes when archived to NSData
. Keeping the amount of data sent to a minimum is crucial to what I'm doing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Martin Gordon 的答案已经很接近了,但幸运的是你不必手动解析 objCType 字符串。有一个函数可以做到这一点: NSGetSizeAndAlignment。由此您可以获得从 getValue: 获得的值的大小/长度。 这个问题 引导我找到解决方案。
我最终为 NSData 创建了一个类别,它允许我从 NSNumber 或 NSValue 对象创建 NSData:
我还在这个 NSValue/NSNumber 数据之前添加了一个小标头,它允许我解码数据所属的属性以及其中有多少字节数据部分。这样我就可以将值恢复到远程属性。
Martin Gordon's answer is getting close, but fortunately you don't have to manually parse the objCType string. There's a function that does that: NSGetSizeAndAlignment. From that you get the size/length of the value obtained from getValue:. This question lead me to the solution.
I ended up creating a category for NSData that allows me to create NSData from NSNumber or NSValue objects:
I also add a small header before this NSValue/NSNumber data that allows me to decode which property the data is for and how many bytes are in the data section. With that I can restore the value to the remote property.
由于
NSValue
采用NSCoding
协议,因此您可以使用NSCoder
子类,NSKeyedArchiver
和NSKeyedUnarchiver
:如果无法使用
NSKeyedArchiver
和NSKeyedUnarchiver
(导致数据大小问题),那么您必须自己查找所包含值的大小:[1]: Objective-C 类型编码
Since
NSValue
adopts theNSCoding
protocol, you can use theNSCoder
subclasses,NSKeyedArchiver
andNSKeyedUnarchiver
:If
NSKeyedArchiver
andNSKeyedUnarchiver
can't be used (for resulting data size issues), then you would have to find the size of the contained value yourself:[1]: Objective-C Type Encodings
您可以使用 NSCoder(如 NSKeyedArchiver)来存档数据,然后发送生成的 NSData。在另一边,您可以将其取消存档。可能有一些警告(例如 http://www .cocoabuilder.com/archive/cocoa/82344-nskeyedarchiver-and-nsvalue.html),特别是如果您正在包装结构并且NSValue 中的其他非存档内容。
You can use NSCoder (like NSKeyedArchiver) to archive the data, then send the resulting NSData. On the other side you can unarchive it. There may be some caveats with this (for example http://www.cocoabuilder.com/archive/cocoa/82344-nskeyedarchiver-and-nsvalue.html) esepcially if you are wrapping structs and other non-archiving stuff in NSValue.