写在前面的话:
GameKit框架在iOS7.0之后已经过时并且传送只能在同一个app之间传送,所以本篇文章仅供学习使用不做推荐!若有兴趣要研究蓝牙技术,请移步至CoreBluetooth框架学习,这个框架现在比较主流,并且可以跨设备传送数据,谢谢!
先附上本人使用GameKit框架写的[蓝牙传输demo]下载地址(https://github.com/ZhuangYuanBaoBao/ZYGameKitDemo.git)
先上效果图:
说明:
图片左边是通过iTools工具将手机屏幕映射在Mac上的图像
图片右边是Xcode运行的模拟器屏幕,现在就是将真机和模拟器进行蓝牙数据(图片)传送。这里传送的数据大小尽量小一点,传的时候快。
实现步骤及说明:
1. General - Deployment Info - Deployment Target - 务必设置7.0以下
2. 导入静态依赖库
①CoreGraphics.framework
②Foundation.framework
③UIKit.framework
④GameKit.framework
3.在ViewController页面包含GameKit/GameKit.h头文件
4.在storyboard上拖入控件建立连接
5.实现相应的按钮方法
①建立连接
- (IBAction)buildConnect:(UIButton *)sender {
//1.创建设备列表控制器 (iOS7.0以下才可以用)
GKPeerPickerController * ppc = [[GKPeerPickerController alloc]init];
//2.设置代理
ppc.delegate = self;
//3.显示控制器 销毁则是dismiss
[ppc show];
}
②发送数据
- (IBAction)sendData:(UIButton *)sender {
if (self.imageView.image == nil) {
return;
}
NSData * data = UIImagePNGRepresentation(self.imageView.image);
//传送模式是可靠的传送 GKSendDataUnReliable则是不可靠的
[self.session sendDataToAllPeers:data withDataMode:GKSendDataReliable error:nil];
}
③实现传送数据代理方法
#pragma mark -- GKPeerPickerControllerDelegate
/**
连接到某个设备就会调用
peerID 设备的蓝牙ID
session 连接会话(通过session通道传输和发送数据)要保存起来这个session,因为传送数据的时候需要这个通道
*/
-(void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session{
// 1.连接结束后 销毁蓝牙连接显示设备的控制器
[picker dismiss];
// 2.保存session 作为传送数据的通道
self.session = session;
// 3.处理接收的数据 (Handler:处理接收数据的句柄对象)
// 接收到蓝牙设备的数据就会自动调用self的 -receiveData:fromPeer:inSession:context:
[self.session setDataReceiveHandler:self withContext:nil];
NSLog(@"didConnectPeer --- %@",peerID);
}
#pragma mark - 接收到蓝牙设备传输的数据,就会自动调用
-(void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:(GKSession *)session context:(void *)context{
self.imageView.image = [UIImage imageWithData:data];
self.sendStatusLabel.text = @"图片接收成功";
// 将图片写入相册
UIImageWriteToSavedPhotosAlbum(self.imageView.image, nil, nil, nil);
}
#pragma mark - 点击取消时调用该函数
- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker{
}
#pragma mark - 设备连接或断开连接时调用该方法
- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
switch (state){
case GKPeerStateConnected:
NSLog(@"connected");
self.connectStatusLabel.text = [NSString stringWithFormat:@"连接设备%@",peerID];
break;
case GKPeerStateDisconnected:
NSLog(@"disconnected");
self.session = nil;
self.connectStatusLabel.text = @"没有连接";
self.sendStatusLabel.text = @"没有图片发送";
break;
default:
break;
}
}
④点击图片区域,从相册选择图片
#pragma mark - 手势(打开相册 选择相片)
- (void)tapClick:(UITapGestureRecognizer *)sender {
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
//如果不是相册 则返回
return;
}
// 1.创建图片选择控制器
UIImagePickerController * ipc = [[UIImagePickerController alloc]init];
ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
// 2.设置代理
ipc.delegate = self;
// 3.显示控制器
[self presentViewController:ipc animated:YES completion:nil];
}
#pragma mark - 监听图片选择
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
// 1.选择完图片后 销毁图片选择控制器
[picker dismissViewControllerAnimated:YES completion:nil];
// 2.显示选中的图片
self.imageView.image = info[UIImagePickerControllerOriginalImage];
}
注:要先选中图片才能发送数据,并且图片选的小一点,传的快,程序会等所有数据传过来才显示图片,没传成功的话,图片区域不会显示要传送的图片,这不是bug,而是数据还没传完~谢谢大家能看完!