Ios 如何使用Game Center SendData向所有玩家发送UIBezierPath

Ios 如何使用Game Center SendData向所有玩家发送UIBezierPath,ios,swift,sprite-kit,nsdata,gamekit,Ios,Swift,Sprite Kit,Nsdata,Gamekit,我有一个从一个玩家向所有玩家发送数据的游戏。我不知道如何发送UIBezierPath对象。我正在将UIBezierPath对象归档到NSData中 以下是我用来发送和接收数据的数据结构: struct DataStruct { var action: Action = Action.Nil var point: CGPoint = CGPoint(x: 0.0, y: 0.0) var path: NSData = NSData() var speed: CGFl

我有一个从一个玩家向所有玩家发送数据的游戏。我不知道如何发送UIBezierPath对象。我正在将UIBezierPath对象归档到NSData中

以下是我用来发送和接收数据的数据结构:

struct DataStruct {
    var action: Action = Action.Nil
    var point: CGPoint = CGPoint(x: 0.0, y: 0.0)
    var path: NSData = NSData()
    var speed: CGFloat = 0.0
}
如果结构中没有NSData,一切正常。使用它,我可以发送数据,但无法接收和获取字节()。我不知道如何对它进行编码和解码。这是有意义的,因为DataStruct的sizeof()不是所发送数据的正确大小。但我找不到这样的例子。任何例子或帮助都将不胜感激。我在发送和接收数据方面的经验有限

以下是我的存档和发送功能:

func sendData(action: Action, point: CGPoint, path: UIBezierPath, speed: CGFloat, mode: GKMatchSendDataMode) {
    // update player position, velocity and angle
    let pathData = NSKeyedArchiver.archivedDataWithRootObject(path)
    var dataStruct = DataStruct(action: action, point: point, path: pathData, speed: speed)
    let data: NSData = NSData(bytes: &dataStruct, length: sizeof(DataStruct))
    do {
        try GameCenterMatch.sendDataToAllPlayers(data, withDataMode: mode)
        print("data sent: \(dataStruct)")
    } catch {
        print("data sent error")
    }
}
以下是我接收它的部分功能:

    func match(match: GKMatch, didReceiveData data: NSData, fromRemotePlayer player: GKPlayer) {
    if GameCenterMatch == match {
        var dataStruct = DataStruct()
        data.getBytes(&dataStruct, length: sizeof(DataStruct))
        print("data received: \(player.displayName), data: \(dataStruct)")

我没有这样做,但有一件事很突出,就是当某些内容(路径)只是指向另一个字节数组的指针时,您正在发送一个字节数组。字符串也会有同样的问题,因为DataStruct的大小是常量,不包括引用内容(如NSData、String、objects等)的内容,而只包括它们的指针


您应该归档数据结构,并在另一端发送该数据结构和未归档数据结构。

我没有这样做,但最突出的一点是,当某些内容(路径)只是指向另一个字节数组的指针时,您正在发送一个字节数组。字符串也会有同样的问题,因为DataStruct的大小是常量,不包括引用内容(如NSData、String、objects等)的内容,而只包括它们的指针


您应该归档数据结构,并在另一端发送该数据结构和未归档数据结构。

多亏了Michael的建议,我创建了一个用于编码和解码的类,它可以正常工作!希望这将有助于其他人在未来

class DataClass: NSObject, NSCoding {
var action: ActionType
var point: CGPoint
var path: UIBezierPath
var speed: CGFloat

override init() {
    self.action = ActionType.Nil
    self.point = CGPoint(x: 0.0, y: 0.0)
    self.path = UIBezierPath()
    self.speed = 0.0

    super.init()
}
init(action: ActionType, point: CGPoint, path: UIBezierPath, speed: CGFloat) {
    self.action = action
    self.point = point
    self.path = path
    self.speed = speed

    super.init()
}

// MARK: NSCoding
required convenience init?(coder decoder: NSCoder) {
    let action = ActionType(rawValue: decoder.decodeIntegerForKey("action")) ?? .Nil
    let point = decoder.decodeCGPointForKey("point")
    let path = decoder.decodeObjectForKey("path") as! UIBezierPath
    let speed = CGFloat(decoder.decodeFloatForKey("speed"))

    self.init(
        action: action,
        point: point,
        path: path,
        speed: speed
    )
}

func encodeWithCoder(coder: NSCoder) {
    coder.encodeInteger(action.rawValue, forKey: "action")
    coder.encodeCGPoint(self.point, forKey: "point")
    coder.encodeObject(self.path, forKey: "path")
    coder.encodeFloat(Float(self.speed), forKey: "speed")
}

}

多亏了Michael的建议,我创建了一个编码和解码类,它可以正常工作!希望这将有助于其他人在未来

class DataClass: NSObject, NSCoding {
var action: ActionType
var point: CGPoint
var path: UIBezierPath
var speed: CGFloat

override init() {
    self.action = ActionType.Nil
    self.point = CGPoint(x: 0.0, y: 0.0)
    self.path = UIBezierPath()
    self.speed = 0.0

    super.init()
}
init(action: ActionType, point: CGPoint, path: UIBezierPath, speed: CGFloat) {
    self.action = action
    self.point = point
    self.path = path
    self.speed = speed

    super.init()
}

// MARK: NSCoding
required convenience init?(coder decoder: NSCoder) {
    let action = ActionType(rawValue: decoder.decodeIntegerForKey("action")) ?? .Nil
    let point = decoder.decodeCGPointForKey("point")
    let path = decoder.decodeObjectForKey("path") as! UIBezierPath
    let speed = CGFloat(decoder.decodeFloatForKey("speed"))

    self.init(
        action: action,
        point: point,
        path: path,
        speed: speed
    )
}

func encodeWithCoder(coder: NSCoder) {
    coder.encodeInteger(action.rawValue, forKey: "action")
    coder.encodeCGPoint(self.point, forKey: "point")
    coder.encodeObject(self.path, forKey: "path")
    coder.encodeFloat(Float(self.speed), forKey: "speed")
}

}

我试试看。假设我必须为结构实现NSCoding并将其更改为类?您可以这样做,也可以创建一个DataStructPer类来实现NSCoding并归档数据结构。我将尝试一下。假设我必须为结构实现NSCoding并将其更改为类?您可以这样做,也可以创建一个DataStructPer类来实现NSCoding并归档数据结构。