iPhone Game Development - Chris Craft [98]
displayName:nil sessionMode:GKSessionModePeer];
The parameters needed for initializing a session are:
sessionID. A unique string that identifies your application.
name. A string identifying the user to display to other peers.
mode. The mode the session should run in.
In P2P Chat, the displayName parameter is set to nil. Setting displayName to nil instructs the picker to use the device name as the displayName. We set the mode to GKSessionModePeer, which tells the session to act as both server and client. This results in the best user experience.
Once you have created the GKSession you begin to send messages. To send a message, you will need to call the method sendDataToAllPeers:withDataMode:error:. This method is used in P2P Chat whenever the Speak button is clicked:
- (IBAction)speakButtonClicked:(id)sender {
if (!isConnected) return;
NSString *message = textField.text;
NSData *data = [message dataUsingEncoding:NSASCIIStringEncoding];
[gameSession sendDataToAllPeers:data withDataMode:GKSendDataReliable error:nil];
}
Take care to notice the parameter data mode. There are two ways to send messages:
GKSendDataReliable. Reliable continues to send the data until it is successfully transmitted. However, it may stall if network congestion occurs. Use this method when you need to guarantee delivery.
GKSendDataUnreliable. Unreliable is the fastest way to send your data. Data is sent one time and does not retry if an error occurs. Data transmitted this way can be received out of order. Use this method for sending small packets of data that must arrive quickly.
The last thing left to do is to implement pertinent methods defined by the protocol GKSessionDelegate:
@protocol GKSessionDelegate @optional - (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state; - (void)session:(GKSession *)session connectionWithPeerFailed:(NSString *)peerID withError:(NSError *)error; - (void)session:(GKSession *)session didFailWithError:(NSError *)error; @end Only one method in this protocol is necessary for P2P Chat. The app needs to know whenever the state of a peer changes relative to the session. For this, the app needs to implement the method session:peer:didChangeState. In this method the app needs to react whenever a peer connects or disconnects. The peer picker will handle all other state changes of concern for us: - (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state { NSString* stateName = nil; switch (state) { case GKPeerStateConnected: [session setDataReceiveHandler: self withContext: nil]; self.isConnected = true; self.gameSession = session; [peerPicker dismiss]; break; case GKPeerStateDisconnected: self.isConnected = false; break; } } Note these two lines of code from above: [session setDataReceiveHandler: self withContext: nil]; and [peerPicker dismiss]; Calling dismiss on the peer picker simply closes the peer picker. However, remember to make the call to get the peer picker off the screen. The call to setDataReceiveHandler:withContext warrants a little more discussion. Setting the DataReceiveHandler tells the GKSession which object to send data to as it arrives from the remote peer. The class receiving the data must implement the following method as P2P Chat has done: - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:(GKSession *)session context:(void *)context { NSString *message = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; textView.text = [textView.text stringByAppendingString: [NSString stringWithFormat:@”%@\n”, message]]; } As illustrated above, whenever data is received from a peer, you can intercept the data in this method and use it in your app as prescribed by your requirements. Researching performance Earlier in the chapter we discussed that network