使用 GameKit 以字节形式发送和接收 NSMutableArray

发布于 2025-01-01 13:57:24 字数 1488 浏览 5 评论 0原文

我正在尝试将数组从一个玩家发送到另一个玩家。

我在标头中创建了一个结构体

typedef struct {
    Message message;
    unsigned int numBytes;
    void * bytes;
} MessagePingBackToCaller;

typedef struct {
    MessageType messageType;
} Message;

并尝试用这个发送:

-(void)sendOpponentRadar{

    MessagePingBackToCaller sendMessage;
    sendMessage.message.messageType = kMessageTypeRecievedRadarPing;
    NSData *pingData = [NSKeyedArchiver archivedDataWithRootObject:[cover gatherAndReturnColumnNumbers]];

    sendMessage.bytes = pingData;

    NSData *data = [NSData dataWithBytes:&sendMessage length:sizeof(MessagePingBackToCaller)];    
    [self sendData:data];
}

并用这个接收:

if (message->messageType == kMessageTypeRecievedRadarPing){

        MessagePingBackToCaller *messageSent = (MessagePingBackToCaller *)[data bytes];

        NSLog(@"Data : %@", messageSent->bytes);

        NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:messageSent->bytes];
        NSLog(@"Results : %@", array);
    }

但是没有运气,所以我环顾四周,发现@rwenderlich写了一些有用的位:

  1. Convert NSArray to NSData

  2. 在 struct 中,存储一个 unsigned int numBytes 和一个 void * bytes

  3. In numBytes,写入NSData的长度,然后写出NSData的内容

  4. 另一边,读取numBytes 来查看接下来要读取多少字节,然后读入该数量的字节并反转该过程(bytes->NSData->NSArray)。

我对 1 和 2 非常擅长...我相信,但我在 3 和 4 上迷失了。有人可以帮我将其翻译成有意义的代码吗?

谢谢!

I am trying to send an Array from one player to another.

I create a struct in the header

typedef struct {
    Message message;
    unsigned int numBytes;
    void * bytes;
} MessagePingBackToCaller;

typedef struct {
    MessageType messageType;
} Message;

And try to send with this:

-(void)sendOpponentRadar{

    MessagePingBackToCaller sendMessage;
    sendMessage.message.messageType = kMessageTypeRecievedRadarPing;
    NSData *pingData = [NSKeyedArchiver archivedDataWithRootObject:[cover gatherAndReturnColumnNumbers]];

    sendMessage.bytes = pingData;

    NSData *data = [NSData dataWithBytes:&sendMessage length:sizeof(MessagePingBackToCaller)];    
    [self sendData:data];
}

And receive with this:

if (message->messageType == kMessageTypeRecievedRadarPing){

        MessagePingBackToCaller *messageSent = (MessagePingBackToCaller *)[data bytes];

        NSLog(@"Data : %@", messageSent->bytes);

        NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:messageSent->bytes];
        NSLog(@"Results : %@", array);
    }

However no luck, so I went looking around and found that @rwenderlich wrote a little helpful bit:

  1. Convert NSArray to NSData

  2. In struct, store an unsigned int numBytes, and a void * bytes

  3. In numBytes, write the length of the NSData, and then write out the contents of the NSData

  4. On the other side, read numBytes to see how many bytes to read next, then read in that amount of bytes and reverse the process (bytes->NSData->NSArray).

Im pretty good on 1 and 2... I believe, but i get lost on 3 and 4. Could someone please help me translate this into meaningful code?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独孤求败 2025-01-08 13:57:24

您可以使用 NSKeyedArchiver 来完成这个技巧,不要使用 c 结构,使其成为 Objective-C 类,使用 NSKeyedArchiver 从事物中获取数据并发送该数据,然后在另一端取消存档,这是任意类的示例

接口

@interface GameState : NSObject
{
   //enum for session state
    SessionState _currentState;
    NSData *_data;
    NSString *_message;

    NSDate *_timestamp;

}

@property(nonatomic,retain) NSDate *timestamp;

@property(assign) SessionState currentState;
@property(nonatomic,retain) NSData *data;
@property(nonatomic,retain) NSString *message;
- (id)initWithCoder:(NSCoder *)coder;

实现

@implementation GameState
@synthesize message=_message ,  currentState= _currentState, data=_data;
@synthesize  timestamp=_timestamp;
- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
        _killPlayback=FALSE;
        _lastPacket=FALSE;
        _number=0.0;
        _pass=FALSE;
        _timestamp=NULL;

    }

    return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:_timestamp forKey:@"Timestamp"];

    [coder encodeObject:_message forKey:@"Message"];
    [coder encodeObject:_data forKey:@"Data"];
    [coder encodeInt:_currentState forKey:@"State"];



}
// Decode an object from an archive
- (id)initWithCoder:(NSCoder *)coder
{
    self = [super init];
    _message  = [[coder decodeObjectForKey:@"Message"] retain];
    _data  = [[coder decodeObjectForKey:@"Data"] retain];
    _currentState=(SessionState)[coder decodeIntForKey:@"State"];
    _timestamp=[[coder decodeObjectForKey:@"Timestamp"] retain];
    return self;
}
@end

现在您可以从对象中获取数据,例如

-(NSData*)dataFromObject:(id)obj
{
    return [NSKeyedArchiver archivedDataWithRootObject:obj];
}

从数据中获取对象

-(id)objectFromData:(NSData*)data
{
    return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}

,您的工作流程就变成了
发送方

GameState *state=..;
NSData* data=[self dataFromObject:state];
//send the data

和接收方

GameState *state=[self objectFromData:data];

希望对您有所帮助

You can just use NSKeyedArchiver to do the trick, dont use the c struct, make it an objective-c class, get data from the thing using NSKeyedArchiver and send that, then just unarchive in the other side, heres an example for an arbitrary class

interface

@interface GameState : NSObject
{
   //enum for session state
    SessionState _currentState;
    NSData *_data;
    NSString *_message;

    NSDate *_timestamp;

}

@property(nonatomic,retain) NSDate *timestamp;

@property(assign) SessionState currentState;
@property(nonatomic,retain) NSData *data;
@property(nonatomic,retain) NSString *message;
- (id)initWithCoder:(NSCoder *)coder;

implementation

@implementation GameState
@synthesize message=_message ,  currentState= _currentState, data=_data;
@synthesize  timestamp=_timestamp;
- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
        _killPlayback=FALSE;
        _lastPacket=FALSE;
        _number=0.0;
        _pass=FALSE;
        _timestamp=NULL;

    }

    return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:_timestamp forKey:@"Timestamp"];

    [coder encodeObject:_message forKey:@"Message"];
    [coder encodeObject:_data forKey:@"Data"];
    [coder encodeInt:_currentState forKey:@"State"];



}
// Decode an object from an archive
- (id)initWithCoder:(NSCoder *)coder
{
    self = [super init];
    _message  = [[coder decodeObjectForKey:@"Message"] retain];
    _data  = [[coder decodeObjectForKey:@"Data"] retain];
    _currentState=(SessionState)[coder decodeIntForKey:@"State"];
    _timestamp=[[coder decodeObjectForKey:@"Timestamp"] retain];
    return self;
}
@end

now you can get data from the object like

-(NSData*)dataFromObject:(id)obj
{
    return [NSKeyedArchiver archivedDataWithRootObject:obj];
}

and an object from the data

-(id)objectFromData:(NSData*)data
{
    return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}

and your workflow becomes
on the sender side

GameState *state=..;
NSData* data=[self dataFromObject:state];
//send the data

and on the receiving side

GameState *state=[self objectFromData:data];

hope it helps

芯好空 2025-01-08 13:57:24

您还可以尝试以下方法来获取压缩数据(大约是原始大小的 1/5):

-(NSData*)compressedMatchDataFromMatchState:(NSMutableDictionary*)matchState
{
    NSError* error = nil;
    NSData* compressedMatchData = [NSPropertyListSerialization dataWithPropertyList:matchState format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error]; 
   return compressedMatchData;
 }

-(NSMutableDictionary*)matchStateFromCompressedMatchData:(NSData*)compressedMatchData
{
    NSError* error = nil;
    NSPropertyListFormat plf = NSPropertyListMutableContainersAndLeaves;
    NSMutableDictionary* matchState = [NSPropertyListSerialization propertyListWithData:compressedMatchData options:NSPropertyListMutableContainersAndLeaves format:&plf error:&error];
    return matchState;
 }

You might also try the following to get compressed data (about 1/5 the size of the original):

-(NSData*)compressedMatchDataFromMatchState:(NSMutableDictionary*)matchState
{
    NSError* error = nil;
    NSData* compressedMatchData = [NSPropertyListSerialization dataWithPropertyList:matchState format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error]; 
   return compressedMatchData;
 }

-(NSMutableDictionary*)matchStateFromCompressedMatchData:(NSData*)compressedMatchData
{
    NSError* error = nil;
    NSPropertyListFormat plf = NSPropertyListMutableContainersAndLeaves;
    NSMutableDictionary* matchState = [NSPropertyListSerialization propertyListWithData:compressedMatchData options:NSPropertyListMutableContainersAndLeaves format:&plf error:&error];
    return matchState;
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文