我正在使用游戏中心在两个玩家之间发送数据。出于某种原因,我不断获得一个解除分配的实例消息。这是代码:
- (void)sendGameMove:(uint32_t)i andj:(NSString *)j {
MessageMove message;
message.message.messageType = kMessageTypeMove;
message.i = 1;
message.j = @"Testing 1 2 3s";
NSData *data = [NSData dataWithBytes:&message length:sizeof(MessageMove)];
MessageMove * messageMove = (MessageMove *) [data bytes];
NSLog(@"Message I: %i", messageMove->i);
NSLog(@"Message J: %@", messageMove->j);
[self sendData:data];
}
(我填写了i和j参数,我正在通过)。在这个方法中,NSLog语句既记录了创建NSData对象之后的内容,又记录了我将NSData对象发送到方法[self sendData:data]:
- (void)sendData:(NSData *)data {
MessageMove * messageMove = (MessageMove *) [data bytes];
NSLog(@"Message I: %i", messageMove->i);
NSLog(@"Message J: %@", messageMove->j);
NSError *error;
BOOL success = [[GCHelper sharedInstance].match sendDataToAllPlayers:data withDataMode:GKMatchSendDataReliable error:&error];
if (!success) {
[self matchEnded];
}
}
在NSLog语句中,第一个工作正常,所以我得到:
"Message I: 1"
在控制台中但是对于我得到的第二个日志语句:
"*** -[ respondsToSelector:]: message sent to deallocated instance"
分解数据对象的代码与第一种方法完全相同。有什么想法吗?
答案 0 :(得分:1)
我猜测MessageMove
是一个类似的结构:
typedef struct {
int i;
NSString *j;
} MessageMove;
问题在于您只发送结构本身的内容。在内存和网络上,它看起来像这样:
01000000 07FCA700
-----------------
i j
当第二个设备收到消息并尝试读取j
指针时,它会崩溃,因为那里没有任何东西:该指针仅在原始设备上有效。该结构甚至根本不包含字符串的内容。
要解决此问题,您需要在邮件中实际发送字符串。灵活的数组成员是直接在结构中存储字符串的一种方法:
typedef struct {
int32_t i; // explicit integer sizes are a good idea for network protocols
int32_t j_length;
char j[]; // the flexible array member
} MessageMove;
发送:
NSString *s = @"Testing 1 2 3s";
NSData *d = [s dataUsingEncoding:NSUTF8StringEncoding];
size_t messageSize = sizeof(MessageMove) + [d length];
MessageMove *mm = calloc(1, messageSize);
mm->i = 1;
mm->j_length = [d length];
memcpy(mm->j, [d bytes], [d length]);
[self sendData:[NSData dataWithBytes:mm length:messageSize]];
接收:
MessageMove *mm = (MessageMove *)[data bytes];
assert(mm->j_length == [data length] - offsetof(MessageMove, j));
NSString *j = [[NSString alloc] initWithBytes:mm->j length:mm->j_length encoding:NSUTF8StringEncoding];
断言阻止读取超过data
缓冲区的末尾。 offsetof
是来自<stddef.h>
的宏。
对于比这更复杂的事情,我建议序列化并发送plist或JSON。它们为您处理所有字符串复制细节,并允许您发送数组和字典。