NSMutableData 到 UnsafeMutableRawPointer 的字节不更新 mutableData 的值
Posted
技术标签:
【中文标题】NSMutableData 到 UnsafeMutableRawPointer 的字节不更新 mutableData 的值【英文标题】:NSMutableData's bytes to UnsafeMutableRawPointer not updating the value of mutableData 【发布时间】:2016-11-02 18:09:57 【问题描述】:我有一个结构对象。还有一个方法,它的输入是有效载荷。现在我正在创建一个名为 packet
的 mutableData,它的可变字节指的是 ICMPHeader 结构。
struct ICMPHeader
var type:UInt8
var code:UInt8
var checksum:UInt16
var identifier:UInt16
var sequenceNumber:UInt16
;
func createPacket(payload:NSData) -> NSData()
var packet:NSMutableData?
var icmpPtr:ICMPHeader = ICMPHeader(type: 0, code: 0, checksum: 0, identifier: 0, sequenceNumber: 0)
packet = NSMutableData(length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
if packet != nil
icmpPtr = packet!.mutableBytes.assumingMemoryBound(to: ICMPHeader.self).pointee
icmpPtr.type = type
icmpPtr.code = 0
icmpPtr.checksum = 0
icmpPtr.identifier = CFSwapInt16BigToHost(identifier)
icmpPtr.sequenceNumber = CFSwapInt16HostToBig(identifier)
memcpy(&icmpPtr + 1, payload.bytes, payload.length)
if (requiresChecksum)
icmpPtr.checksum = in_cksum(packet!.bytes, bufferLen: packet!.length);
return packet
可变字节已成功绑定到结构,并且结构ICMPHeader
中的值也得到更新。
问题在于更改 struct 中的值不会更改可变数据 packet
的值。
如果我在创建结构后尝试重新创建数据包,那么它就会崩溃。
package = NSMutableData(bytes: unsafeBitCast(icmpPtr, to: UnsafeMutableRawPointer.self), length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
【问题讨论】:
【参考方案1】:我在 XCode 8.1 Swift 发行说明中找到了答案。
在 struct object icmpPtr
进行更改后,我已将其更改回缓冲区指针。
var byteBuffer = [UInt8]()
withUnsafeBytes(of: &icmpPtr)
(bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
package.replaceBytes(in: NSMakeRange(0, byteBuffer.count), withBytes: byteBuffer)
所以我没有创建新的 Data 对象,而是替换了字节,它就像一个魅力。
根据文档:
XCode 8.1 发行说明: https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html 快速部分:
一个新的 withUnsafeBytes(of:) 函数暴露了一个值的内存 表示为 UnsafeRawBufferPointer。这个例子复制了一个 将异构结构体转换为同构字节数组:
struct Header var x: Int var y: Float var header = Header(x: 0, y: 0.0) var byteBuffer = [UInt8]() withUnsafeBytes(of: &header) (bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
一个新的 Array.withUnsafeBytes 方法公开了一个数组的底层 缓冲区作为 UnsafeRawBufferPointer。这个例子复制了一个数组 整数转换为字节数组:
let intArray = [1, 2, 3] var byteBuffer = [UInt8]() intArray.withUnsafeBytes (bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
所以最终的实现是
struct ICMPHeader
var type:UInt8
var code:UInt8
var checksum:UInt16
var identifier:UInt16
var sequenceNumber:UInt16
;
func createPacket(payload:NSData) -> NSData()
var packet:NSMutableData?
var icmpPtr:ICMPHeader = ICMPHeader(type: 0, code: 0, checksum: 0, identifier: 0, sequenceNumber: 0)
packet = NSMutableData(length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
if packet != nil
icmpPtr = packet!.mutableBytes.assumingMemoryBound(to: ICMPHeader.self).pointee
icmpPtr.type = type
icmpPtr.code = 0
icmpPtr.checksum = 0
icmpPtr.identifier = CFSwapInt16BigToHost(identifier)
icmpPtr.sequenceNumber = CFSwapInt16HostToBig(identifier)
memcpy(&icmpPtr + 1, payload.bytes, payload.length)
if (requiresChecksum)
icmpPtr.checksum = in_cksum(packet!.bytes, bufferLen: packet!.length);
var byteBuffer = [UInt8]()
withUnsafeBytes(of: &icmpPtr)
(bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
packet.replaceBytes(in: NSMakeRange(0, byteBuffer.count), withBytes: byteBuffer)
return packet
【讨论】:
以上是关于NSMutableData 到 UnsafeMutableRawPointer 的字节不更新 mutableData 的值的主要内容,如果未能解决你的问题,请参考以下文章
asihttp 使用 POST 方法并将 nsMutabledata 发布到 uri,为啥我无法获得 asi 委托回调?
如何将NSString直接分配给NSMutableData?
将 NSMutableData 转换为 NSURL 用于 ios 中的视频
Objective-C NSData/NSMutableData
通过 Cocoa 类在 Objective Pascal 单元中将 AnsiString 转换或转换为 NSMutableData