有this answer for using [UInt8],但似乎使用各种指针API,我不能在数据上找到。
我想基本上一些自定义扩展看起来像:
let input = 42.13 // implicit Doublelet bytes = input.datalet roundtrip = bytes.to(Double) // --> 42.13
这部分真的逃避了我,我看过一堆文档,是我怎么能从任何基本结构(所有的数字)得到一些指针事物(OpaquePointer或BufferPointer或UnsafePointer?)。在C,我只是在它前面拍了一个&符号,并有ya去。
如何从值创建数据struct Data有一个初始化器
public init(bytes: UnsafeRawPointer,count: Int)
其可以以与对问题的各种答案类似的方式使用
How to convert a double into a byte array in swift?
您链接到:
let input = 42.13var value = inputlet data = withUnsafePointer(to: &value) { Data(bytes: UnsafePointer(public init<SourceType>(buffer: UnsafeBufferPointer<SourceType>)),count: MemoryLayout.size(ofValue: input))}print(data as NSData) // <713d0ad7 a3104540>
因为@zneak已经说过,你可以只取一个变量的地址,
因此,使用var value = value创建一个变量副本。
在早期的Swift版本中,你可以通过做
函数参数本身是一个变量,这不再支持了。
但是,使用初始化程序更容易
let input = 42.13var value = inputlet data = Data(buffer: UnsafeBufferPointer(start: &value,count: 1))print(data as NSData) // <713d0ad7 a3104540>
代替:
public func withUnsafeBytes<ResultType,ContentType>(_ body: @noescape (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType
请注意,通用占位符SourceType将从中自动推断
上下文。
如何从数据中检索值
NSData有一个bytes属性来访问底层存储。
struct数据有一个通用
let data = Data(bytes: [0x71,0x3d,0x0a,0xd7,0xa3,0x10,0x45,0x40])let value = data.withUnsafeBytes { (ptr: UnsafePointer<Double>) -> Double in return ptr.pointee}print(value) // 42.13
相反,它可以这样使用:
let data = Data(bytes: [0x71,0x40])let value: Double = data.withUnsafeBytes {extension Data { init<T>(from value: T) { var value = value self.init(buffer: UnsafeBufferPointer(start: &value,count: 1)) } func to<T>(type: T.Type) -> T { return self.withUnsafeBytes {.pointee }print(value) // 42.13let input = 42.13 // implicit Doublelet data = Data(from: input)print(data as NSData) // <713d0ad7 a3104540>let roundtrip = data.to(type: Double.self)print(roundtrip) // 42.13.pointee } }}
如果ContentType可以从上下文推断,则不需要指定它
在闭包中,这样可以简化为
extension Data { init<T>(fromArray values: [T]) { var values = values self.init(buffer: UnsafeBufferPointer(start: &values,count: values.count)) } func toArray<T>(type: T.Type) -> [T] { return self.withUnsafeBytes { [T](UnsafeBufferPointer(start:let input: [Int16] = [1,Int16.max,Int16.min]let data = Data(fromArray: input)print(data as NSData) // <0100ff7f 0080>let roundtrip = data.toArray(type: Int16.self)print(roundtrip) // [1,32767,-32768],count: self.count/MemoryLayout<T>.strIDe)) } }}
通用解决方案#1
以上转换现在可以轻松实现为struct的通用方法Data:
protocol DataConvertible { init?(data: Data) var data: Data { get }}
例:
extension DataConvertible { init?(data: Data) { guard data.count == MemoryLayout<Self>.size else { return nil } self = data.withUnsafeBytes {extension Int : DataConvertible { }extension float : DataConvertible { }extension Double : DataConvertible { }// add more types here ....pointee } } var data: Data { var value = self return Data(buffer: UnsafeBufferPointer(start: &value,count: 1)) }}
类似地,您可以将数组转换为数据并返回:
let input = 42.13let data = input.dataprint(data as NSData) // <713d0ad7 a3104540>if let roundtrip = Double(data: data) { print(roundtrip) // 42.13}
例:
extension String: DataConvertible { init?(data: Data) { self.init(data: data,enCoding: .utf8) } var data: Data { // Note: a conversion to UTF-8 cannot fail. return self.data(using: .utf8)! }}
通用解决方案#2
上述方法有一个缺点:
How to convert a double into a byte array in swift?,
它实际上只与“简单”
类型如整数和浮点类型。 “复杂”类型如Array
和String有(隐藏)指向底层存储的指针,不能
通过只复制结构本身传递。它也不会工作
引用类型只是指向真实对象存储的指针。
所以解决这个问题,一个可以
>定义一个协议,定义转换为数据并返回的方法:
>在协议扩展中将转换实现为默认方法:
我在这里选择一个可用的初始化程序,检查提供的字节数
匹配类型的大小。
>最后声明符合所有类型,可以安全地转换为数据并返回:
这使得转换更加优雅:
第二种方法的优点是,您不能无意中执行不安全的转化。
缺点是你必须显式列出所有“安全”类型。
您还可以为需要非平凡的其他类型实现协议
转换,如:
或者在你自己的类型中实现转换方法来做任何事情必须这样序列化和反序列化一个值。
总结以上是内存溢出为你收集整理的往返Swift数字类型到/从数据全部内容,希望文章能够帮你解决往返Swift数字类型到/从数据所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)