nik*_*ers 18 serialization struct nskeyedarchiver nsdata swift
我有一个结构包含一个结构NSObject
,我想序列化到一个NSData
对象:
struct Packet {
var name: String
var index: Int
var numberOfPackets: Int
var data: NSData
}
var thePacket = Packet(name: name, index: i, numberOfPackets: numberOfPackets, data: packetData)
Run Code Online (Sandbox Code Playgroud)
我如何最好地将数据包序列化为一个NSData
,以及如何最好地将其反序列化?
运用
var bufferData = NSData(bytes: & thePacket, length: sizeof(Packet))
Run Code Online (Sandbox Code Playgroud)
只给了我名字和数据的指针.我正在探索NSKeyedArchiver
,但后来我必须使Packet成为一个对象,我宁愿保持它的结构.
干杯
聂
nik*_*ers 11
没有得到任何反馈,这是我最终得到的解决方案:
encode()
和decode()
功能Int
到Int64
这样的Int
具有在32位和64位平台相同的尺寸Data
,但只有Int64
这是我的代码,我将非常感谢您的反馈,特别是如果有更简单的方法来做到这一点:
public struct Packet {
var name: String
var index: Int64
var numberOfPackets: Int64
var data: NSData
struct ArchivedPacket {
var index : Int64
var numberOfPackets : Int64
var nameLength : Int64
var dataLength : Int64
}
func archive() -> NSData {
var archivedPacket = ArchivedPacket(index: Int64(self.index), numberOfPackets: Int64(self.numberOfPackets), nameLength: Int64(self.name.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)), dataLength: Int64(self.data.length))
var metadata = NSData(
bytes: &archivedPacket,
length: sizeof(ArchivedPacket)
)
let archivedData = NSMutableData(data: metadata)
archivedData.appendData(name.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!)
archivedData.appendData(data)
return archivedData
}
func unarchive(data: NSData!) -> Packet {
var archivedPacket = ArchivedPacket(index: 0, numberOfPackets: 0, nameLength: 0, dataLength: 0)
let archivedStructLength = sizeof(ArchivedPacket)
let archivedData = data.subdataWithRange(NSMakeRange(0, archivedStructLength))
archivedData.getBytes(&archivedPacket)
let nameRange = NSMakeRange(archivedStructLength, Int(archivedPacket.nameLength))
let dataRange = NSMakeRange(archivedStructLength + Int(archivedPacket.nameLength), Int(archivedPacket.dataLength))
let nameData = data.subdataWithRange(nameRange)
let name = NSString(data: nameData, encoding: NSUTF8StringEncoding) as! String
let theData = data.subdataWithRange(dataRange)
let packet = Packet(name: name, index: archivedPacket.index, numberOfPackets: archivedPacket.numberOfPackets, data: theData)
return packet
}
}
Run Code Online (Sandbox Code Playgroud)
小智 9
对于基本结构对象来说,最简单的方法是PropertyListEncoder 和 PropertyListDecoder。
这是示例代码;
雨燕5
struct Packet: Codable {
var name: String
var index: Int
var numberOfPackets: Int
var data: Data
}
func getDataFromPacket(packet: Packet) -> Data?{
do{
let data = try PropertyListEncoder.init().encode(packet)
return data
}catch let error as NSError{
print(error.localizedDescription)
}
return nil
}
func getPacketFromData(data: Data) -> Packet?{
do{
let packet = try PropertyListDecoder.init().decode(Packet.self, from: data)
return packet
}catch let error as NSError{
print(error.localizedDescription)
}
return nil
}
Run Code Online (Sandbox Code Playgroud)
这是来自Xcode 8.2.1中的Playground的未经修改的复制粘贴.它比其他答案简单一些.
import Foundation
enum WhizzoKind {
case floom
case bzzz
}
struct Whizzo {
let name: String
let num: Int
let kind:WhizzoKind
static func archive(w:Whizzo) -> Data {
var fw = w
return Data(bytes: &fw, count: MemoryLayout<Whizzo>.stride)
}
static func unarchive(d:Data) -> Whizzo {
guard d.count == MemoryLayout<Whizzo>.stride else {
fatalError("BOOM!")
}
var w:Whizzo?
d.withUnsafeBytes({(bytes: UnsafePointer<Whizzo>)->Void in
w = UnsafePointer<Whizzo>(bytes).pointee
})
return w!
}
}
let thing = Whizzo(name:"Bob", num:77, kind:.bzzz)
print("thing = \(thing)")
let dataThing = Whizzo.archive(w: thing)
let convertedThing = Whizzo.unarchive(d: dataThing)
print("convertedThing = \(convertedThing)")
Run Code Online (Sandbox Code Playgroud)
我无法制作archive
和unarchive
实例方法因为 Data.init(bytes:?count:?)
在bytes
参数上发生变异?并且self
不是可变的,所以......这对我来说毫无意义.
该WhizzoKind
枚举是在那里,因为这是我关心的.这个例子并不重要.有人可能像我一样对于enums感到偏执.
我不得不从另外4个问题/答案中拼凑出这个答案:
这些文档: - http://swiftdoc.org/v3.1/type/UnsafePointer/
并且冥想Swift闭包语法,直到我想要尖叫.
所以感谢那些其他的SO问题/作者.
所以这不适用于各种设备.例如,从iPhone 7发送到Apple Watch.因为stride
不同.以上示例在iPhone 7 Simulator上为80字节,但在Apple Watch Series 2 Simulator上为40字节.
看起来@niklassaers的方法(但不是语法)仍然是唯一可行的方法.我将在这里留下这个答案,因为它可能会帮助其他人围绕这个主题进行所有新的Swift 3语法和API更改.
我们唯一真正的希望就是这个Swift提案:https://github.com/apple/swift-evolution/blob/master/proposals/0166-swift-archival-serialization.md
归档时间: |
|
查看次数: |
15425 次 |
最近记录: |