使用NSKeyedArchiver通过消息对象发送数据

时间:2013-03-19 15:52:05

标签: ios objective-c cocos2d-iphone

我正在实施一个多人游戏,我必须使用以下方式在玩家之间发送数据:

 [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;

Submessage 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];

但是,当我发送Submessage时,这不起作用。如何确定数据类型是Message还是Submessage?我应该如何实现它,以便它在c-struct情况下工作?

2 个答案:

答案 0 :(得分: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:将检测子类,这就是为什么第一个条件需要在这里检查子类。)

答案 1 :(得分:0)

您的子类initWithCoder似乎不正确。根据文件:

  

如果超类采用NSCoding协议,则首先进行分配   initWithCoder的返回值:自我:

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

但是既然你说消息长度应该最小化,我建议使用MessagePack(http://msgpack.org/)来转换为紧凑的二进制表示。你必须自己处理更多,但它应该更有效率:)