Swift 3、Multipeer,发送struct as Data
Swift 3, Multipeer, send struct as Data
我正在努力解决一个问题。我想向连接的设备发送一个结构。
这是我使用的复制到 Playground 中的代码
在代码中,我为 coding/decoding 的数据 class 添加了一些扩展。我创建了 [String:Player] 的字典并使用 NSKeyedArchiver 创建要发送的数据记录。
我不在此处发送,但在我的程序中发送。在操场上,code/decode 工作正常。当我在我的程序中执行此操作时,从数据中提取播放器时解码失败。它失败了:EXC_BAD_ACCESS
如果我使用 String 而不是 Player 结构,它可以在 didReceive 数据函数中正常解码。仅在使用结构时失败。
有人有什么建议吗?
//: Playground - noun: a place where people can play
import UIKit
// Player structure
struct Player {
var initials : String
var name : String
}
//
// Data extension
//
extension Data {
// struct
init<T>(from value: T) {
var value = value
self.init(bytes: &value, count: MemoryLayout<T>.size)
}
// extract Struct
func extract<T>(from: T.Type) -> T {
return self.withUnsafeBytes { [=11=].pointee } // FAILS HERE: EXC_BAD_ACCESS
}
}
// Make a data record for sending
let sply = Player(initials: "PN", name: "Player Name")
let spda = Data(from: sply)
let sdic : [String:Data] = ["Player" : spda]
let sdta : Data = NSKeyedArchiver.archivedData(withRootObject: sdic)
// Do the sending
// ... send...
//Decode
// The following code that is used on the receiving device in
// the "didReceive data" function.
let rdic = NSKeyedUnarchiver.unarchiveObject(with: sdta) as! [String : Data]
let rdta = rdic["Player"]!
let rply = rdta.extract(from: Player.self)
print(rply.name) // Prints: "Player Name"
对我有用的是自定义 class,它继承自 NSObject 并符合 NSCoding。
class Player: NSObject, NSCoding {
var initials: String!
var name: String!
required convenience init(coder decoder: NSCoder) {
self.init()
self.initials = decoder.decodeObject(forKey: "initials") as! String
self.name = decoder.decodeObject(forKey: "name") as! String
}
convenience init(initials: String, name: String) {
self.init()
self.initials = initials
self.name = name
}
func encode(with aCoder: NSCoder) {
if let initials = initials { aCoder.encode(initials, forKey: "initials") }
if let name = name { aCoder.encode(name, forKey: "name") }
}
}
制作要发送的数据:
let data = NSKeyedArchiver.archivedData(withRootObject: Player(initials: "PN", name: "Player Name"))
将数据返回给播放器:
guard let player: Player = NSKeyedUnarchiver.unarchiveObject(with: data) as! Player? else { return }
我正在努力解决一个问题。我想向连接的设备发送一个结构。
这是我使用的复制到 Playground 中的代码
在代码中,我为 coding/decoding 的数据 class 添加了一些扩展。我创建了 [String:Player] 的字典并使用 NSKeyedArchiver 创建要发送的数据记录。
我不在此处发送,但在我的程序中发送。在操场上,code/decode 工作正常。当我在我的程序中执行此操作时,从数据中提取播放器时解码失败。它失败了:EXC_BAD_ACCESS
如果我使用 String 而不是 Player 结构,它可以在 didReceive 数据函数中正常解码。仅在使用结构时失败。
有人有什么建议吗?
//: Playground - noun: a place where people can play
import UIKit
// Player structure
struct Player {
var initials : String
var name : String
}
//
// Data extension
//
extension Data {
// struct
init<T>(from value: T) {
var value = value
self.init(bytes: &value, count: MemoryLayout<T>.size)
}
// extract Struct
func extract<T>(from: T.Type) -> T {
return self.withUnsafeBytes { [=11=].pointee } // FAILS HERE: EXC_BAD_ACCESS
}
}
// Make a data record for sending
let sply = Player(initials: "PN", name: "Player Name")
let spda = Data(from: sply)
let sdic : [String:Data] = ["Player" : spda]
let sdta : Data = NSKeyedArchiver.archivedData(withRootObject: sdic)
// Do the sending
// ... send...
//Decode
// The following code that is used on the receiving device in
// the "didReceive data" function.
let rdic = NSKeyedUnarchiver.unarchiveObject(with: sdta) as! [String : Data]
let rdta = rdic["Player"]!
let rply = rdta.extract(from: Player.self)
print(rply.name) // Prints: "Player Name"
对我有用的是自定义 class,它继承自 NSObject 并符合 NSCoding。
class Player: NSObject, NSCoding {
var initials: String!
var name: String!
required convenience init(coder decoder: NSCoder) {
self.init()
self.initials = decoder.decodeObject(forKey: "initials") as! String
self.name = decoder.decodeObject(forKey: "name") as! String
}
convenience init(initials: String, name: String) {
self.init()
self.initials = initials
self.name = name
}
func encode(with aCoder: NSCoder) {
if let initials = initials { aCoder.encode(initials, forKey: "initials") }
if let name = name { aCoder.encode(name, forKey: "name") }
}
}
制作要发送的数据:
let data = NSKeyedArchiver.archivedData(withRootObject: Player(initials: "PN", name: "Player Name"))
将数据返回给播放器:
guard let player: Player = NSKeyedUnarchiver.unarchiveObject(with: data) as! Player? else { return }