由于对等网络连接过程有点复杂,贯穿了这些协议和类,我们绘制了连接过程的流程图。
下面我们通过代码直接介绍连接流程,其中ViewController.h代码如下:
- #import <UIKit/UIKit.h>
- #import <GameKit/GameKit.h>
- #define GAMING 0 //游戏进行中
- #define GAMED 1 //游戏结束
- @interface ViewController : UIViewController <GKSessionDelegate, GKPeerPickerControllerDelegate>
- {
- NSTimer *timer;
- }
- @property (weak, nonatomic) IBOutlet UILabel *lblTimer;
- @property (weak, nonatomic) IBOutlet UILabel *lblPlayer2;
- @property (weak, nonatomic) IBOutlet UILabel *lblPlayer1;
- @property (weak, nonatomic) IBOutlet UIButton *btnConnect;
- @property (weak, nonatomic) IBOutlet UIButton *btnClick;
- @property (nonatomic, strong) GKPeerPickerController *picker;
- @property (nonatomic, strong) GKSession *session;
- - (IBAction)onClick:(id)sender;
- - (IBAction)connect:(id)sender;
- //清除UI画面上的数据
- -(void) clearUI;
- //更新计时器
- -(void) updateTimer;
- @end
ViewController.m中创建GKPeerPickerController对象的代码如下:
_picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby | GKPeerPickerConnectionTypeOnline;
其中“在线”就是GKPeerPickerConnectionTypeOnline类型,“附近”就是GKPeerPickerConnectionTypeNearby类型。
连接成功之后回调ViewController.m中的回调委托方法peerPickerController:didConnectPeer:toSession:代码:
- - (void)peerPickerController:(GKPeerPickerController *)pk didConnectPeer:(NSString *)peerID
- toSession:(GKSession *) session
- {
- NSLog(@”建立连接”);
- _session = session; ①
- _session.delegate = self; ②
- [_session setDataReceiveHandler:self withContext:nil]; ③
- _picker.delegate = nil;
- [_picker dismiss]; ④
- [_btnClick setEnabled:YES];
- [_btnConnect setTitle:@"断开连接" forState:UIControlStateNormal];
- //开始计时
- timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
- selector:@selector(updateTimer)
- userInfo:nil repeats:YES]; ⑤
- }
有的时候会话的状态会发生变化,我们要根据状态的变化做一些UI的清理和资源的释放。监测状态变化在委托方法session:peer:didChangeState:中实现,方法代码如下:
- - (void)session:(GKSession *)session peer:(NSString *)peerID
- didChangeState:(GKPeerConnectionState)state
- {
- if (state == GKPeerStateConnected)
- {
- NSLog(@”connected”);
- [_btnConnect setTitle:@"断开连接" forState:UIControlStateNormal];
- [_btnClick setEnabled:YES];
- } else if (state == GKPeerStateDisconnected)
- {
- NSLog(@”disconnected”);
- [self clearUI];
- }
- }
其中GKPeerStateConnected常量是已经连接状态,GKPeerStateDisconnected常量是断开连接状态。
- - (IBAction)onClick:(id)sender {
- int count = [_lblPlayer1.text intValue];
- _lblPlayer1.text = [NSString stringWithFormat:@"%i",++count];
- NSString *sendStr = [NSString
- stringWithFormat:@"{\"code\":%i,\"count\":%i}",GAMING,count]; ①
- NSData* data = [sendStr dataUsingEncoding: NSUTF8StringEncoding];
- if (_session) {
- [_session sendDataToAllPeers:data
- withDataMode:GKSendDataReliable error:nil]; ②
- }
- }
- - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer
- inSession:(GKSession *)session context:(void *)context
- {
- id jsonObj = [NSJSONSerialization JSONObjectWithData:data
- options:NSJSONReadingMutableContainers error:nil];
- NSNumber *codeObj = [jsonObj objectForKey:@"code"];
- if ([codeObj intValue]== GAMING) {
- NSNumber * countObj= [jsonObj objectForKey:@"count"];
- _lblPlayer2.text = [NSString stringWithFormat:@"%@",countObj];
- } else if ([codeObj intValue]== GAMED) {
- [self clearUI];
- }
- }
上面的代码是接收到数据之后,进行JSON解码,取出游戏状态和点击次数。
主要的程序代码就是这些,根据具体的业务情况还可以能有所变化,读者可以下载完整代码在两台之间设备或是一个设备一个模拟器之间进行测试。