2016-04-01 14 views
1

我正在使用GameKit进行多人Swift(XCode 7.3/iOS 9.2)游戏。通过GKMatchDelegate检查整个结构didReceiveData

我使用自定义结构作为通过GameKit发送的信息。下面是结构的副本。 frustrationNetworkMessage是一个字符串枚举&卡是一个单独的类(如果需要的话可以张贴代码)

struct frustrationNetworkMessage { 
var messageType : FrustrationNetworkMessageType 
var cards : [Card] 
var actingPlayer : String 

init(messageType : FrustrationNetworkMessageType, cards : [Card], actingPlayer : String) { 
    self.messageType = messageType 
    self.cards = cards 
    self.actingPlayer = actingPlayer 
} 

我的问题是在'比赛(比赛:GKMatch,didReceiveData数据:NSData的,fromRemotePlayer球员:GKPlayer)'方法。我已经工作了,这是被称为曾有数据被接收:

private var receivedData : NSMutableData 

func decode<T>(data: NSData) -> T { 
    let pointer = UnsafeMutablePointer<T>.alloc(sizeof(T.Type)) 
    data.getBytes(pointer, length: sizeof(T)) 
    return pointer.move() 
} 

func match(match: GKMatch, didReceiveData data: NSData, fromRemotePlayer player: GKPlayer) { 
    print("Match/did receive data: size of data - \(sizeofValue(data))") 
    receivedData.appendData(data) 
    if let receivedNetworkMessage : frustrationNetworkMessage = decode(receivedData) { 
     print("Match/did receive data: \(receivedNetworkMessage.messageDetails())") 

当我运行它崩溃在与EXC_BAD_ACCESS(我的理解是它抱怨它试图访问的一部分,最终打印语句上面的代码尚未收到的结构)。

作为一个例子:

消息摘要在发送 - >sendNetworkMessage:消息类型:startNewGame与actingPlayer:G:118279601 &卡计数:1 - 消息大小:40

消息长度第一次匹配didReceiveData被调用 - >匹配/确实接收数据:数据大小 - 8

我该如何检查在执行操作之前我已经获得了整个结构?我曾经想过更新结构以包含一个长度字段(理论上我应该一直收到 - 因此可以用它来检查数据包的长度)。

回答

0

您可以使用像这样的后台进程来持续检查您的数据结构吗?

newQueue = NSOperationQueue()

let operation2 = NSBlockOperation(block: { 


    }) 

operation2.completionBlock = { 
    print("Operation 2 completed") 
} 

let operation1 = NSBlockOperation(block: { 


    }) 

operation1.completionBlock = { 

    self.newQueue.addOperation(operation2) 
} 

operation1.qualityOfService = .UserInitiated 
newQueue.addOperation(operation1) 
} 

初始化变量,然后检查其长度;这将保存/停止崩溃。

0

我发现了一个微小的答案(问题已在代码的其他地方移动)

struct frustrationNetworkMessage { 
var messageType : FrustrationNetworkMessageType 
var card : Card 
var actingPlayer : String 

init(messageType : FrustrationNetworkMessageType, card : Card, actingPlayer : String) { 
    self.messageType = messageType 
    self.card = card 
    self.actingPlayer = actingPlayer 
} 

init(data : NSData) { 
    let messageTypeLength = sizeofValue(FrustrationNetworkMessageType) 
    let cardLength = sizeofValue(Card) 

    let messageTypeRange = NSMakeRange(0, messageTypeLength) 
    let cardLengthRange = NSMakeRange(messageTypeLength, messageTypeLength + cardLength) 
    let actingPlayerRange = NSMakeRange(messageTypeLength + cardLength, data.length) 

    self.messageType = .didDiscardCard 
    self.card = Card.emptyCard() 

    data.getBytes(&self.messageType, range: messageTypeRange) 
    data.getBytes(&self.card, range: cardLengthRange) 
    let actingPlayerData = data.subdataWithRange(actingPlayerRange) 
    self.actingPlayer = NSString(data: actingPlayerData, encoding: NSUTF8StringEncoding) as! String 
} 

func archive()->NSData { 
    var localMessageType = messageType.rawValue 
    var localCard = card 

    let returnValue = NSMutableData(bytes: &localMessageType, length: sizeofValue(self.messageType.rawValue)) 
    returnValue.appendData(NSData(bytes: &localCard, length: sizeofValue(self.card))) 
    returnValue.appendData(actingPlayer.dataUsingEncoding(NSUTF8StringEncoding)!) 
    return returnValue 
} 

什么我已经通过试验发现错误(和大量的后续读):

  1. 比赛didReceiveData似乎只能当它接收到整个包被调用(所以不需要办理接收部分数据)

  2. 如果可能避免ENC将类数据类型编码为NSData(通过挖掘,我发现我只编码本地地址,如果通过本地传递 - 通过网络传输不会太好)。接近我的所有数据类型,既​​可以是基本类型(所有枚举现在是UInt8类型)或结构。