0

以下を使用してプレイヤー間でデータを送信する必要があるマルチプレイヤー ゲームを実装しています。

 [self sendData:data mode:GKMatchSendDataReliable];

このチュートリアルのように複数の c-struct を使用する代わりに ( http://www.raywenderlich.com/3325/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-22 ) 、 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;
}

サブメッセージ.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];

ただし、サブメッセージを送信している場合、これは機能しません。データのタイプが Message か Submessage かを判断するにはどうすればよいですか? c-struct の場合のように動作するようにするには、これをどのように実装すればよいですか?

4

2 に答える 2

0

initWithCoder をサブクラス化するのは正しくないようです。ドキュメントによると:

スーパークラスが NSCoding プロトコルを採用している場合は、initWithCoder: の戻り値を self に割り当てることから始めます。

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

しかし、メッセージの長さを最小限に抑える必要があると言っているので、コンパクトなバイナリ表現に変換するためにMessagePack ( http://msgpack.org/ ) を使用することをお勧めします。もう少し自分で処理する必要がありますが、はるかに効率的です:)

于 2013-03-20T17:58:11.917 に答える
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:はサブクラスを検出します。そのため、ここで最初の条件をサブクラスのチェックにする必要があります。)

于 2013-03-19T16:09:49.090 に答える