In this example, PositionPacket is just a structure. The next line then places this structure in NSData, which is a byte bucket object.
NSData *packet = [NSData dataWithBytes: &msg length: sizeof(PositionPacket)];
So, if you just want to send an int score, you can have a sendScore method that looks like this:
- (void) sendScore { NSError *error; int myScore = self.score; NSData *packet = [NSData dataWithBytes:&myScore length:sizeof(myScore)]; [match sendDataToAllPlayers: packet withDataMode: GKMatchSendDataUnreliable error: &error]; if (error != nil) {
As a rule, you will need a structure, so there is additional information that allows recipients to find out what data they have. In this example, this would be the goal of this line:
msg.messageKind = PositionMessage;
In general, you can send whatever you want to encapsulate into an NSData object, as it is just a byte bucket. You can send primitive types such as ints or structs, as in the example, or even NSObjects (provided that they implement NSCoding). You should read NSKeyedArchiver, NSCoding, and NSData for more information about sending and receiving NSObjects this way. Here is the Apple Archiving help document.
As for the reception, you do not call this method, it receives a call from you on Kit. This is what is called the "delegate method" (in Cocoa parlance) or the "callback method". You can think of it as a “phone call," which your application can receive asynchronously. Using the signature method:
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID;
... you say: "I can get this phone call." Therefore, when GameKit receives data on your behalf from another player, it will see that you want to receive callbacks of this type and then called by this method - then you need to update your internal state of the application based on the received one.
To continue this example, if you sent the simple “nothing but the whole” message described above, you can implement this method as follows:
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID { int* receivedScorePtr = (int*)[data bytes]; int receivedScore = *receivedScorePtr; [self updateScore: received forPlayer: playerID]; }
This, of course, assumes that you have a method called updateScore: forPlayer: this will update the score table.
You can find a more general discussion / explanation of how delegates and delegation methods work in this blog post: http://mohrt.blogspot.com/2010/01/cocoa-and-delegates.html
ADDED: Using the code sent by the appellator, I made several modifications and released a version that “works” for this case using bare bones. A working version of a test application for sending one whole through GameCenter. I do not pretend to the quality of the code or its suitability for everything. I did not write 99.9% of this, please do not accept my messages here as confirmation of what appears in it.
One of the lessons (I did not know, so I hope this helps others) is that you cannot use Matchmaking with a simulator. This means that you need two iOS devices with development support to test this scenario, and probably for non-trivial programs, two development machines to debug both devices at the same time. This problem cost me the most when I figured it out.