一、概述
利用GameKit框架实现ios设备的蓝牙通讯,导入框架:#import <GameKit/GameKit.h> , 注意: 此框架只能用于ios设置间蓝牙通讯。
如今苹果开放了接口来实现不仅限于在苹果设备间的蓝牙通讯,需要导入框架:#import <CoreBluetooth/CoreBluetooth.h>,此框架可以用在苹果设备间、苹果设备与各种符合苹果MFI认证的智能硬件的蓝牙通信。
以一个简单的APP聊天功能作为示例,讲解使用GameKit的蓝牙通信功能以及UITableView的自定义cell的使用方法。
二、用GameKit框架实现ios设备蓝牙通讯
基本属性和方法:
属性:
- 是否可见:visible
- 蓝牙连接类型:connectionTypesMask
方法:
- 显示蓝牙控制器:- (void)show;
- 隐藏蓝牙控制器:- (void)dismiss;
- 蓝牙连接成功会调用:- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
- 取消蓝牙连接:- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
- 接收到数据会调用:- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
- 发送数据给特定的对端蓝牙设备:self.session sendData:<#(NSData *)#> toPeers:<#(NSArray *)#> withDataMode:<#(GKSendDataMode)#> error:<#(NSError *__autoreleasing *)#>
- 发送数据给所有蓝牙设备:self.session sendDataToAllPeers:<#(NSData *)#> withDataMode:<#(GKSendDataMode)#> error:<#(NSError *__autoreleasing *)#>
Apple提供了一个内置的界面“对等设备选择器”,可用于查找要连接的设备,如下如所示,可以让用户轻易的查找并选择设备连接。
具体实现方式如下:
//初始化对等设备把设置代理
GKPeerPickerController* peerPickerController=[[GKPeerPickerController alloc] init];
peerPickerController.delegate=self;
peerPickerController.connectionTypesMask=GKPeerPickerConnectionTypeNearby;
self.peerPickerController=peerPickerController;
[self.peerPickerController show];
//代理方法,用户点取消按钮调用
-(void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
{
self.peerPickerController.delegate=nil;
}
//代理方法,用户选择连接某个设备时调用,连接建立一个会话
-(void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
[self.peerPickerController dismiss];
SZChatVC* chatVC=[[SZChatVC alloc] init];
chatVC.currrentSession=session;
chatVC.peerID=peerID;
[self.navigationController pushViewController:chatVC animated:YES];
}
//发送消息
- (IBAction)send:(id)sender
{
NSString* messageStr=self.inputTextField.text;
NSDictionary* messageDict=[[NSDictionary alloc] initWithObjectsAndKeys:messageStr,@"message",@"myself",@"sender", nil];
[messageArray addObject:messageDict];
NSLog(@"messageArray:%@",messageArray);
NSError *error=nil;
NSData* messageData=[messageStr dataUsingEncoding:NSUTF8StringEncoding];
//通过前面连接的蓝牙会话发送数据
[self.currrentSession sendDataToAllPeers:messageData withDataMode:GKSendDataReliable error:&error];
if (error)
{
NSLog(@"Current session is error:%@",error);
}
//情况输入框和使发送按钮非使能
[self.inputTextField setText:@""];
[self.sendBtn setEnabled:NO];
//刷新信息表格,滚动到底部
[self.messageTableView reloadData];
NSLog(@"[messageArray count]:%lu",[messageArray count]);
NSIndexPath* indexPathLast=[NSIndexPath indexPathForRow:[messageArray count]-1 inSection:0];
[self.messageTableView scrollToRowAtIndexPath:indexPathLast atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
//接收消息
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
NSString *messageString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *messageDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:messageString, @"message", @"peer", @"sender", nil];
[messageArray addObject: messageDictionary];
[self.messageTableView reloadData];
//scroll to the last row
NSIndexPath* indexPathForLastRow = [NSIndexPath indexPathForRow:[messageArray count]-1 inSection:0];
[self.messageTableView scrollToRowAtIndexPath:indexPathForLastRow atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
三、自定义cell显示消息(类似于微信消息对话界面)
由于系统提供的tableview可能并不能满足我们的开发需求,所以经常要求我们能够自定义tableview。
自定义tableview有两种方式,一种是使用xib创建,一种是使用纯代码的方式创建。
对于样式一样的tableview,通常使用xib进行创建,对于高度不一样,内容也不完全一致的通常使用纯代码进行自定义。具体实现如下:
//代理方法,设置cell
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIImageView* messageBackground=nil;
UILabel* messageLabel=nil;
//cell重用
NSString* const cellID=@"cellID";
UITableViewCell* cell=[tableView dequeueReusableCellWithIdentifier:cellID];
if (!cell)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
//自定义的从cell主要包含了一个聊天气泡的背景视图和一个显示消息文本的Label
messageBackground=[[UIImageView alloc] init];
messageBackground.backgroundColor=[UIColor clearColor];
//设置cell的concentView的tag,注意contentView的tag不能为0,否则程序崩溃
messageBackground.tag=kmsgBackground;
messageLabel=[[UILabel alloc] init];
messageLabel.tag=kmsgText;
messageLabel.numberOfLines=0;
messageLabel.lineBreakMode=NSLineBreakByCharWrapping;
messageLabel.font=[UIFont systemFontOfSize:14];
}
else
{
messageBackground=(UIImageView*)[cell.contentView viewWithTag:kmsgBackground];
messageLabel=(UILabel*)[cell.contentView viewWithTag:kmsgText];
}
//取出当前cell的消息
NSDictionary* messageDict=[messageArray objectAtIndex:indexPath.row];
NSString* messageStr=[messageDict objectForKey:@"message"];
NSString* sender=[messageDict objectForKey:@"sender"];
//根据消息文本计算cell的大小
CGSize messageSize=[messageStr sizeWithFont:[UIFont systemFontOfSize:14.] constrainedToSize:CGSizeMake(180, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
UIImage* bubbleImage;
CGFloat tableViewWidth=self.messageTableView.frame.size.width;
if ([sender isEqualToString:@"myself"])
{
//设置消息气泡背景大小
messageBackground.frame=CGRectMake(tableViewWidth-messageSize.width-34,1, messageSize.width+34, messageSize.height+12.);
messageBackground.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin;
//拉伸聊天气泡图片
bubbleImage=[[UIImage imageNamed:@"chatBubbleGreen"] stretchableImageWithLeftCapWidth:15 topCapHeight:13];
//设置消息文本标签的大小
messageLabel.frame=CGRectMake(tableViewWidth-messageSize.width-22., 5., messageSize.width+5, messageSize.height);
messageLabel.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin;
}
else
{
//同上设置方法
messageBackground.frame=CGRectMake(0.,1., messageSize.width+34, messageSize.height+12.);
messageBackground.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin;
bubbleImage=[[UIImage imageNamed:@"chatBubbleGray"] stretchableImageWithLeftCapWidth:23 topCapHeight:15];
messageLabel.frame=CGRectMake(22., 5., messageSize.width+5, messageSize.height);
messageLabel.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin;
}
messageBackground.image=bubbleImage;
messageLabel.text=messageStr;
[cell.contentView addSubview:messageBackground];
[cell.contentView addSubview:messageLabel];
return cell;
}
//代理方法,设置cell的高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString* messageStr=[[messageArray objectAtIndex:indexPath.row] objectForKey:@"message"];
CGSize messageSize=[messageStr sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(180, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
return messageSize.height+17.0f;
}
结果如下: