2013-03-19 146 views
0

我實現多人遊戲,我必須使用派球員之間的數據發送數據:除了通過消息對象使用的NSKeyedArchiver

[self sendData:data mode:GKMatchSendDataReliable]; 

在本教程中(http://www.raywenderlich.com/3325/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-22)使用多個C-結構一樣的,我創建了一個Message對象和一個名爲Submessage的Message的子類。創建子類是爲了避免在每條消息中發送不必要的變量,以儘量減少每個發送的數據包的大小。然後我使用NSCoding對消息進行編碼和解碼。

的類看起來像下面這樣:

Message.h

@interface Message : NSObject <NSCoding> 

@property int messageType; 

- (void)encodeWithCoder:(NSCoder*)coder; 

- (id)initWithCoder:(NSCoder*)coder; 

信息編碼器方法

-(void) encodeWithCoder:(NSCoder *)coder{ 
    [coder encodeInt:messageType forKey:@"messageType"]; 
} 
-(id)initWithCoder:(NSCoder *)coder { 
    self = [super init]; 
    messageType = [coder decodeIntForKey:@"messageType"]; 
    return self; 
} 

Submessage.h

@interface Submessage : Message <NSCoding> 

@property float additionalParameter1; 

- (void)encodeWithCoder:(NSCoder*)coder; 

- (id)initWithCoder:(NSCoder*)coder; 

分消息編碼器方法

- (void)encodeWithCoder:(NSCoder *)coder{ 
    [super encodeWithCoder:coder]; 
    [coder encodeFloat:additionalParameter1 forKey:@"float"]; 
} 

- (id)initWithCoder:(NSCoder *)coder { 
    self = [super init]; 
    [self initWithCoder:coder]; 
    floatParameter1 = [coder decodeFloatForKey:@"floatParameter1"]; 
    return self; 
} 

我收到數據後,我用下面的方法來解除封存:

Message *thisMessage = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 

然而,這並不在我的工作發送子消息。我如何確定數據是消息類型還是子消息類型?我應該如何實現這一點,以便它能像在c-struct情況下一樣工作?

+0

通過_doesn't work_,你的意思是說'[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:submessage]]'返回一個實例'Message'而不是'Submessage'? – Taum 2013-03-19 16:02:19

+0

另外,您可能想要展示如何實現'initWithCoder'方法。 – Taum 2013-03-19 16:05:46

+0

您擔心數據包的大小,但您正在發送歸檔數據。您是否檢查了由於開銷造成的大型密鑰存檔?您可能會發送超過200個字節的數據,而不是8個字節。 – LearnCocos2D 2013-03-19 19:18:54

回答

0

你的子類的initWithCoder似乎並不正確。根據文檔:

如果父採用NSCoding協議,您可以通過分配的initWithCoder的返回值的 開始:自我:

- (id)initWithCoder:(NSCoder *)coder { 
    self = [super initWithCoder:coder]; 
    if (self) { 
     // Implementation continues. 
    } 
    return self; 
} 

但既然你說的消息長度應該最小化,我建議使用MessagePack(http://msgpack.org/)轉換爲緊湊的二進制表示。你必須自己處理更多,但它應該更有效率:)

+0

另外,使用你的調試器來檢查Submessage的initWithCoder是否確實被調用! – Taum 2013-03-20 17:58:49

+0

謝謝,並且還建議使用MessagePack! – jyek 2013-03-20 23:21:45

0

如果我理解你的問題,你想在運行時確定什麼樣的對象被取消存檔。您可以像使用任何對象一樣測試它的類,然後適當地使用它。像這樣:

id obj = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
if ([obj isKindOfClass:[Submessage class]]) { 
    Submessage * submessage = (Submessage *)obj; 
    // do something with submessage 
} else if ([obj isKindOfClass:[Message class]]) { 
    Message * message = (Message *)obj; 
    // do something with message 
} 

-isKindOfClass:將檢測的子類,這就是爲什麼第一個條件需要是子類中的檢查這裏)