2016-04-01 41 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類型)或結構。