iOS中 蓝牙2.0详解/ios蓝牙设备详解

版权声明:本文为博主原创文章,未经博主允许不得转载。

每日更新关注:http://weibo.com/hanjunqiang  新浪微博

整体布局如下:

    程序结构如右图:

每日更新关注:http://weibo.com/hanjunqiang  新浪微博

==========================================================================

指定根视图:

[objc] view plain copy

  1. RootViewController * rootVC = [[RootViewController alloc] init];  
  2. UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:rootVC];  
  3. self.window.rootViewController= nav;  

根视图:

[objc] view plain copy

  1. #import "RootViewController.h"  
  2. #import "BlueSessionManager.h"  
  3. #import "ChatCell.h"  
  4. #import "ChatItem.h"  
  5.   
  6. #import <AssetsLibrary/AssetsLibrary.h>  
  7. #import <AVFoundation/AVFoundation.h>  
  8.   
  9.   
  10. #define kRecordAudioFile @"myRecord.caf"  
  11.   
  12. // 判断大小  
  13. #define HEIGHT [UIScreen mainScreen].bounds.size.height  
  14. #define WIDTH [UIScreen mainScreen].bounds.size.width  
  15. #define ChatHeight 45.0  
  16.   
  17. @interface RootViewController ()<NSStreamDelegate,UITableViewDataSource,UITableViewDelegate,UITextViewDelegate,UIActionSheetDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate,AVAudioRecorderDelegate,AVAudioPlayerDelegate>  
  18. {  
  19.     float _sendBackViewHeight;  
  20.     float _sendTextViewHeight;  
  21.       
  22.     UIImagePickerController * _picker;  
  23.     UIView * _backRemindRecordView;  
  24. }  
  25.   
  26. // DataAndBlue  
  27. @property(strong, nonatomic) BlueSessionManager *sessionManager;  
  28.   
  29. @property(strong, nonatomic) NSMutableArray *datasource;  
  30. @property(strong, nonatomic) NSMutableArray * myDataArray;  
  31.   
  32. @property(strong, nonatomic) NSMutableData *streamData;  
  33. @property(strong, nonatomic) NSOutputStream *outputStream;  
  34. @property(strong, nonatomic) NSInputStream *inputStream;  
  35.   
  36. // UI  
  37. @property(strong, nonatomic) UITableView * tableView;  
  38. @property(strong, nonatomic) UIView * sendBackView;  
  39. @property(strong, nonatomic) UITextView * sendTextView;  
  40. @property(strong, nonatomic) UIButton * sendButton;  
  41.   
  42.   
  43. // 语音播放  
  44. @property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音频录音机  
  45. //音频播放器,用于播放录音文件  
  46. @property (nonatomic,strong) AVAudioPlayer *audioPlayer;  
  47.   
  48. @property (nonatomic,strong) NSTimer *timer;//录音声波监控(注意这里暂时不对播放进行监控)  
  49.   
  50.   
  51.   
  52. @property (strong, nonatomic) UIProgressView *audioPower;//音频波动  
  53.   
  54.   
  55.   
  56.   
  57. @end  
  58.   
  59. @implementation RootViewController  
  60.   
  61. - (void)viewDidLoad {  
  62.     [super viewDidLoad];  
  63.       
  64.     [self makeBlueData];  
  65.       
  66.     [self readyUI];  
  67.       
  68.     [self buildVideoForWe];  
  69.       
  70.       
  71.     // Do any additional setup after loading the view  
  72. }  
  73.   
  74.   
  75.   
  76.   
  77. #pragma mark  基本制作  
  78.   
  79. - (void)readyUI  
  80. {  
  81.     self.title = @"蓝牙设置";  
  82.     self.view.backgroundColor = [UIColor whiteColor];  
  83.     self.automaticallyAdjustsScrollViewInsets = NO;  
  84.       
  85.     NSArray * buttonTitleArray = @[@"寻找设备",@"打开天线"];  
  86.     self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:buttonTitleArray[0] style:UIBarButtonItemStyleDone target:self action:@selector(lookOtherDevice)];  
  87.     self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:buttonTitleArray[1] style:UIBarButtonItemStyleDone target:self action:@selector(showSelfAdvertiser)];  
  88.     [self makeUIView];  
  89.       
  90. }  
  91. - (void)lookOtherDevice  
  92. {  
  93.     [self.sessionManager browseWithControllerInViewController:self connected:^{  
  94.         NSLog(@"connected");  
  95.     }                                                 canceled:^{  
  96.         NSLog(@"cancelled");  
  97.     }];  
  98. }  
  99.   
  100.   
  101. - (void)showSelfAdvertiser  
  102. {  
  103.     [self.sessionManager advertiseForBrowserViewController];  
  104. }  
  105.   
  106. #pragma mark 制作页面UI  
  107. - (void)makeUIView  
  108. {  
  109. //    NSLog(@"width === %f,height===== %f",WIDTH,HEIGHT);  
  110.       
  111.     self.myDataArray = [NSMutableArray arrayWithCapacity:0];  
  112.       
  113.     self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10)];  
  114.     self.tableView.delegate = self;  
  115.     self.tableView.dataSource = self;  
  116.     self.tableView.separatorStyle = UITableViewCellSelectionStyleNone;  
  117.      
  118.     [self.view addSubview:self.tableView];  
  119.       
  120.      
  121.       
  122.       
  123.      
  124. //-------------------------------------------------------------------------//  
  125.       
  126.     self.sendBackView = [[UIView alloc] initWithFrame:CGRectMake(0, HEIGHT - ChatHeight, WIDTH, ChatHeight)];  
  127.     self.sendBackView.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];  
  128.     [self.view addSubview:self.sendBackView];  
  129.       
  130. //    float heightView = self.sendBackView.frame.size.height;  
  131.       
  132.     self.sendTextView = [[UITextView alloc] initWithFrame:CGRectMake(10, 5, WIDTH - 10 - 90, 35)];  
  133. //    self.sendTextView.backgroundColor = [UIColor lightGrayColor];  
  134.     self.sendTextView.returnKeyType = UIReturnKeySend;  
  135.     self.sendTextView.font = [UIFont systemFontOfSize:17];  
  136.     self.sendTextView.editable = YES;  
  137.     self.sendTextView.delegate = self;  
  138.     [self.sendBackView addSubview:self.sendTextView];  
  139.       
  140.     UIButton * addButton = [UIButton buttonWithType:UIButtonTypeContactAdd];  
  141.     addButton.frame = CGRectMake(WIDTH - 85, 2, 37, 37);  
  142.     [addButton addTarget:self action:@selector(addNextImage) forControlEvents:UIControlEventTouchUpInside];  
  143.     [self.sendBackView addSubview:addButton];  
  144.       
  145.     self.sendButton = [UIButton buttonWithType:UIButtonTypeCustom];  
  146.     self.sendButton.frame = CGRectMake(WIDTH - 45, 5, 40, 30);  
  147.       
  148.     [self.sendButton setImage:[UIImage imageNamed:@"record.png"] forState:UIControlStateNormal];  
  149.     [self.sendButton addTarget:self action:@selector(videoRecord) forControlEvents:UIControlEventTouchUpInside];  
  150.     [self.sendBackView addSubview:self.sendButton];  
  151.       
  152.     
  153.       
  154.       
  155.     // 增加通知  
  156.     [self addTheNoticeForKeyDownUp];  
  157.       
  158. }  
  159.   
  160.   
  161. #pragma mark 图片的传输---------///////  
  162.   
  163. - (void)addNextImage  
  164. {  
  165.      
  166.     UIActionSheet *chooseImageSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"照相机",@"相册", nil nil];  
  167.     [chooseImageSheet showInView:self.view];  
  168. }  
  169.   
  170.   
  171.   
  172.   
  173. #pragma mark UIActionSheetDelegate Method  
  174. -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex  
  175. {  
  176.     _picker = [[UIImagePickerController alloc] init];  
  177.     _picker.delegate = self;  
  178.       
  179.     switch (buttonIndex) {  
  180.         case 0://Take picture  
  181.               
  182.        
  183.             if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])  
  184.             {  
  185.                   
  186.                 _picker.sourceType = UIImagePickerControllerSourceTypeCamera;  
  187.             }  
  188.           
  189.             [self presentViewController:_picker animated:NO completion:nil];  
  190.               
  191.               
  192.         
  193.             break;  
  194.               
  195.         case 1:  
  196.             //From album  
  197.             _picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;  
  198.               
  199.             [self presentViewController:_picker animated:NO completion:^{  
  200.                   
  201.                 // 改变状态栏的颜色  为正常  这是这个独有的地方需要处理的  
  202.                 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];  
  203.             }];  
  204.             break;  
  205.               
  206.         default:  
  207.               
  208.             break;  
  209.     }  
  210. }  
  211.   
  212.   
  213.   
  214.   
  215.   
  216.   
  217.   
  218. // 相册  
  219. -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info  
  220. {  
  221.       
  222.     NSString *type = [info objectForKey:UIImagePickerControllerMediaType];  
  223.     //当选择的类型是图片  
  224.     if ([type isEqualToString:@"public.image"])  
  225.     {  
  226.         //先把图片转成NSData  
  227.         UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];  
  228.         NSData *data;  
  229.         if (UIImagePNGRepresentation(image) == nil)  
  230.         {  
  231.             data = UIImageJPEGRepresentation(image, 1.0);  
  232.         }  
  233.         else  
  234.         {  
  235.             data = UIImagePNGRepresentation(image);  
  236.         }  
  237.           
  238.         //图片保存的路径  
  239.         //这里将图片放在沙盒的documents文件夹中  
  240.         NSString * DocumentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];  
  241.           
  242.         //文件管理器  
  243.         NSFileManager *fileManager = [NSFileManager defaultManager];  
  244.           
  245.         //把刚刚图片转换的data对象拷贝至沙盒中 并保存为image.png  
  246.         [fileManager createDirectoryAtPath:DocumentsPath withIntermediateDirectories:YES attributes:nil error:nil];  
  247.         [fileManager createFileAtPath:[DocumentsPath stringByAppendingString:@"/image.png"] contents:data attributes:nil];  
  248.           
  249.         //得到选择后沙盒中图片的完整路径  
  250.         NSString * filePath = [[NSString alloc]initWithFormat:@"%@%@",DocumentsPath,  @"/image.png"];  
  251.           
  252.           
  253.           
  254.         [_picker dismissViewControllerAnimated:NO completion:^{  
  255.               
  256.             // 改变状态栏的颜色  改变为白色  
  257.             [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];  
  258.               
  259.               
  260.               
  261.             // 这边是真正的发送  
  262.             if(!self.sessionManager.isConnected)  
  263.             {  
  264.                 UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"蓝牙已经断开了,请重新连接!" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil nil];  
  265.                 [alertView show];  
  266.                 return;  
  267.             }  
  268.               
  269.             ChatItem * chatItem = [[ChatItem alloc] init];  
  270.             chatItem.isSelf = YES;  
  271.             chatItem.states = picStates;  
  272.             chatItem.picImage = image;  
  273.             [self.datasource addObject:chatItem];  
  274.               
  275.               
  276.             [self insertTheTableToButtom];  
  277.               
  278.               
  279.             [self sendAsResource:filePath];  
  280.              
  281.         }];  
  282.     }  
  283.   
  284.     
  285. }  
  286. - (void)sendAsResource:(NSString *)path  
  287. {  
  288.       
  289.     NSLog(@"dispaly ====%@",self.sessionManager.firstPeer.displayName);  
  290.     NSString * name = [NSString stringWithFormat:@"%@ForPic",[[UIDevice currentDevice] name]];  
  291.     NSURL * url = [NSURL fileURLWithPath:path];  
  292.       
  293.     NSProgress *progress = [self.sessionManager sendResourceWithName:name atURL:url toPeer:self.sessionManager.firstPeer complete:^(NSError *error) {  
  294.         if(!error) {  
  295.             NSLog(@"finished sending resource");  
  296.         }  
  297.         else {  
  298.             NSLog(@"%@", error);  
  299.         }  
  300.     }];  
  301.     NSLog(@"%@", @(progress.fractionCompleted));  
  302. }  
  303.   
  304.   
  305. #pragma mark 普通数据的传输  
  306. - (void)sendWeNeedNews  
  307. {  
  308.     if(!self.sessionManager.isConnected)  
  309.     {  
  310.         UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"蓝牙已经断开了,请重新连接!" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil nil];  
  311.         [alertView show];  
  312.         return;  
  313.     }  
  314.     if([self.sendTextView.text isEqualToString:@""])  
  315.     {  
  316.         return;  
  317.     }  
  318.       
  319.       
  320.     ChatItem * chatItem = [[ChatItem alloc] init];  
  321.     chatItem.isSelf = YES;  
  322.     chatItem.states = textStates;  
  323.     chatItem.content = self.sendTextView.text;  
  324.     [self.datasource addObject:chatItem];  
  325.     // 加到数组里面  
  326.       
  327.     // 添加行   indexPath描述位置的具体信息  
  328.     [self insertTheTableToButtom];  
  329.       
  330.     NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.sendTextView.text];  
  331.     NSError *error = [self.sessionManager sendDataToAllPeers:data];  
  332.     if(!error) {  
  333.         //there was no error.  
  334.     }  
  335.     else {  
  336.         NSLog(@"%@", error);  
  337.     }  
  338.       
  339.     [self returnTheNewBack];  
  340. }  
  341. - (void)returnTheNewBack  
  342. {  
  343.     // 归零  
  344.     self.sendTextView.text = @"";  
  345.     [self.sendTextView resignFirstResponder];  
  346.     self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10 );  
  347.     self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight , WIDTH, ChatHeight);  
  348.       
  349. }  
  350.   
  351. // 这是一种很好的键盘下移方式  
  352. -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text  
  353. {  
  354.       
  355.     if ([text isEqualToString:@"\n"]) {  
  356.           
  357.         [self sendWeNeedNews];  
  358.   
  359.         return NO;  
  360.     }  
  361.       
  362.       
  363.       
  364.       
  365.     return YES;  
  366. }  
  367.   
  368. - (void)textViewDidChange:(UITextView *)textView  
  369. {  
  370.   
  371.     // 随机改变其高度  
  372.       
  373.     float textHeight = [self heightForString:textView.text fontSize:16 andWidth:textView.frame.size.width];  
  374.     _sendTextViewHeight = textHeight;  
  375. //    NSLog(@"teztheight ===== %f",textHeight);  
  376.       
  377.       
  378.     self.sendTextView.frame = CGRectMake(10, 5, WIDTH - 10 - 90, _sendTextViewHeight);  
  379.     self.sendBackView.frame = CGRectMake(0, HEIGHT -  _sendBackViewHeight - _sendTextViewHeight - 10, WIDTH, _sendTextViewHeight + 10);  
  380.     
  381.       
  382. }  
  383.   
  384. - (float) heightForString:(NSString *)value fontSize:(float)fontSize andWidth:(float)width  
  385. {  
  386.     UITextView *detailTextView = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, width, 0)];  
  387.     detailTextView.font = [UIFont systemFontOfSize:fontSize];  
  388.     detailTextView.text = value;  
  389.     CGSize deSize = [detailTextView sizeThatFits:CGSizeMake(width,CGFLOAT_MAX)];  
  390.     return deSize.height;  
  391. }  
  392.   
  393.   
  394.   
  395. #pragma mark 以下是为了配合  键盘上移的变化  
  396.   
  397. - (void)addTheNoticeForKeyDownUp  
  398. {  
  399.     [ [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyBoardDidShow:) name:UIKeyboardDidShowNotification object:nil];  
  400.     [ [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];  
  401. }  
  402.   
  403. - (void)dealloc  
  404. {  
  405.     [[NSNotificationCenter defaultCenter] removeObserver:self];  
  406. }  
  407.   
  408. -(void)handleKeyBoardDidShow:(NSNotification *)paramNotification  
  409. {  
  410.     CGSize size = [[paramNotification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;  
  411.       
  412.     _sendBackViewHeight = size.height;  
  413.       
  414.     [UIView animateWithDuration:0.000001 animations:^{  
  415.         self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - size.height);  
  416.         self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight - size.height, WIDTH, ChatHeight);  
  417.           
  418.     }];  
  419.       
  420. }  
  421. -(void)handleKeyboardWillHide:(NSNotification *)paramNotification  
  422. {  
  423.     [UIView animateWithDuration:0.1 animations:^{  
  424.         if(_sendTextViewHeight > 0)  
  425.         {  
  426.             self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - _sendTextViewHeight + 10 );  
  427.             self.sendBackView.frame = CGRectMake(0, HEIGHT - _sendTextViewHeight  - 10, WIDTH, _sendTextViewHeight + 10);  
  428.         }  
  429.         else  
  430.         {  
  431.             self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10 );  
  432.             self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight , WIDTH, ChatHeight);  
  433.         }  
  434.           
  435.           
  436.     }];  
  437. }  
  438. /*--------------------------------------------------------------------------------------------*/  
  439. - (void)insertTheTableToButtom  
  440. {  
  441.     // 哪一组 哪一段  
  442.     NSIndexPath * indexPath = [NSIndexPath indexPathForRow:self.datasource.count- 1 inSection:0];  
  443.     // 添加新的一行  
  444.     [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];  
  445.     // 滑动到底部  第二个参数是滑动到底部  
  446.     [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];  
  447. }  
  448.   
  449. #pragma mark tableView 代理  
  450. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {  
  451.     return 1;  
  452. }  
  453.   
  454. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {  
  455.     return self.datasource.count;  
  456. }  
  457.   
  458. -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath  
  459. {  
  460.     ChatItem * chatItem = [self.datasource objectAtIndex:indexPath.row];  
  461.     if(chatItem.states == picStates)  
  462.     {  
  463.         NSLog(@"widht====%f,height======%f",chatItem.picImage.size.width,chatItem.picImage.size.height);  
  464.         return 50;  
  465.           
  466.           
  467.           
  468.     }  
  469.     else if(chatItem.states == textStates)  
  470.     {  
  471.         CGSize size = [chatItem.content boundingRectWithSize:CGSizeMake(250, 1000) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading  attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:14]} context:nil].size;  
  472.           
  473.         return size.height + 20 + 10; // 与view的距离 + 与Cell的距离  
  474.     }  
  475.     else  
  476.     {  
  477.         return 50;  
  478.     }  
  479.       
  480.       
  481. }  
  482.   
  483. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  
  484. {  
  485.       
  486.     static NSString * iden = @"iden";  
  487.     ChatCell * cell = [tableView dequeueReusableCellWithIdentifier:iden];  
  488.     if(cell == nil)  
  489.     {  
  490.         cell = [[ChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:iden];  
  491.         cell.selectionStyle = UITableViewCellSelectionStyleNone;  
  492.         // 让后面选中的没有阴影效果  
  493.           
  494.     }  
  495.       
  496.     // 模型  
  497.       
  498.     ChatItem * chatItem = [self.datasource objectAtIndex:indexPath.row];  
  499.      
  500.     CGSize size = [chatItem.content boundingRectWithSize:CGSizeMake(250, 1000) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading  attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:14]} context:nil].size;  
  501.       
  502.     //如果自己发的  
  503.     if(chatItem.isSelf)  
  504.     {  
  505.         cell.leftHeadImage.hidden = YES;  
  506.         cell.rightHeadImage.hidden = NO;  
  507.           
  508.         if(chatItem.states == picStates)  
  509.         {  
  510.             cell.lefeView.hidden = YES;  
  511.             cell.rightView.hidden = YES;  
  512.               
  513.             cell.rightPicImage.image = chatItem.picImage;  
  514.             cell.leftPicImage.hidden = YES;  
  515.             cell.rightPicImage.hidden = NO;  
  516.               
  517.             cell.leftVideoButton.hidden = YES;  
  518.             cell.rightVideoButton.hidden = YES;  
  519.               
  520.             NSLog(@"self send");  
  521.              
  522.               
  523.         }  
  524.         else if(chatItem.states == textStates)  
  525.         {  
  526.             cell.rightPicImage.hidden = YES;  
  527.             cell.leftPicImage.hidden = YES;  
  528.               
  529.             cell.lefeView.hidden = YES;  
  530.             cell.rightView.hidden = NO;  
  531.               
  532.             cell.leftVideoButton.hidden = YES;  
  533.             cell.rightVideoButton.hidden = YES;  
  534.             // 复用机制  
  535.             cell.rightLabel.frame = CGRectMake(10, 5, size.width, size.height);  
  536.             cell.rightView.frame = CGRectMake(WIDTH - 40 -size.width-25, 5, size.width + 25, size.height + 18);  
  537.             cell.rightLabel.text = chatItem.content;  
  538.         }  
  539.         else  
  540.         {  
  541.             cell.rightView.hidden = YES;  
  542.             cell.lefeView.hidden = YES;  
  543.             cell.rightView.hidden = YES;  
  544.             cell.lefeView.hidden = YES;  
  545.               
  546.             cell.leftVideoButton.hidden = YES;  
  547.             cell.rightVideoButton.hidden = NO;  
  548.               
  549.             cell.rightVideoButton.tag = 300 + indexPath.row;  
  550.             [cell.rightVideoButton addTarget:self action:@selector(cellSelectIndex:) forControlEvents:UIControlEventTouchUpInside];  
  551.             [cell.rightVideoButton setImage:[UIImage imageNamed:@"record.png"] forState:UIControlStateNormal];  
  552.               
  553.         }  
  554.           
  555.           
  556.           
  557.           
  558.           
  559.           
  560.           
  561.     }  
  562.     else  // 接受得到  
  563.     {  
  564.         cell.leftHeadImage.hidden = NO;  
  565.         cell.rightHeadImage.hidden = YES;  
  566.          
  567.           
  568.           
  569.         if(chatItem.states == picStates)  
  570.         {  
  571.             cell.rightView.hidden = YES;  
  572.             cell.lefeView.hidden = YES;  
  573.               
  574.             cell.leftVideoButton.hidden = YES;  
  575.             cell.rightVideoButton.hidden = YES;  
  576.               
  577.             cell.leftPicImage.image = chatItem.picImage;  
  578.             cell.rightPicImage.hidden = YES;  
  579.             cell.leftPicImage.hidden = NO;  
  580.               
  581.              
  582.               
  583.               
  584.         }  
  585.         else if(chatItem.states == textStates)  
  586.         {  
  587.             cell.rightPicImage.hidden = YES;  
  588.             cell.leftPicImage.hidden = YES;  
  589.               
  590.             cell.rightView.hidden = YES;  
  591.             cell.lefeView.hidden = NO;  
  592.               
  593.             cell.leftVideoButton.hidden = YES;  
  594.             cell.rightVideoButton.hidden = YES;  
  595.               
  596.             cell.leftLabel.frame = CGRectMake(15, 5, size.width, size.height);  
  597.               
  598.             cell.lefeView.frame = CGRectMake(40, 5, size.width +30, size.height + 25);  
  599.               
  600.             cell.leftLabel.text = chatItem.content;  
  601.         }  
  602.         else  
  603.         {  
  604.             cell.rightView.hidden = YES;  
  605.             cell.lefeView.hidden = YES;  
  606.             cell.rightView.hidden = YES;  
  607.             cell.lefeView.hidden = YES;  
  608.               
  609.             cell.leftVideoButton.hidden = NO;  
  610.             cell.rightVideoButton.hidden = YES;  
  611.               
  612.               
  613.             cell.leftVideoButton.tag = 300 + indexPath.row;  
  614.             [cell.leftVideoButton setImage:[UIImage imageNamed:@"record.png"] forState:UIControlStateNormal];  
  615.             [cell.leftVideoButton addTarget:self action:@selector(cellSelectIndex:) forControlEvents:UIControlEventTouchUpInside];  
  616.         }  
  617.           
  618.           
  619.           
  620.     }  
  621.   
  622.       
  623.     return cell;  
  624. }  
  625.   
  626. - (void)cellSelectIndex:(UIButton *)cellBtn  
  627. {  
  628.       
  629.     ChatItem *chatIden = [self.datasource objectAtIndex:cellBtn.tag - 300];  
  630.     if(chatIden.states == videoStates)  
  631.     {  
  632.         NSLog(@"realy play");  
  633. //        [self makeVideoPlayer:[self getVideoStremData]];  
  634.         [self makeVideoPlayer:chatIden.recordData];  
  635.     }  
  636. }  
  637.   
  638.   
  639. #pragma mark 下面是核心的连接MCSession 和  数据返回的地方  
  640.   
  641. /***************************-------**********************************************/  
  642. - (void)makeBlueData  
  643. {  
  644.       // 这是为了让 在block中弱引用  
  645.     __weak typeof (self) weakSelf = self;  
  646.     self.datasource = [NSMutableArray arrayWithCapacity:0];  
  647.       
  648.     // 初始化  会议室  
  649.     self.sessionManager = [[BlueSessionManager alloc]initWithDisplayName:[NSString stringWithFormat:@" %@",  [[UIDevice currentDevice] name]]];  
  650.       
  651.     //  
  652.     [self.sessionManager didReceiveInvitationFromPeer:^void(MCPeerID *peer, NSData *context) {  
  653.         __strong typeof (weakSelf) strongSelf = weakSelf;  
  654.         UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"是否连接?" message:[NSString stringWithFormat:@"同 %@%@", peer.displayName, @" 连接?"] delegate:strongSelf cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil nil];  
  655.         [alertView show];  
  656.     }];  
  657.       
  658.     [self.sessionManager peerConnectionStatusOnMainQueue:YES block:^(MCPeerID *peer, MCSessionState state) {  
  659.         if(state == MCSessionStateConnected) {  
  660.             UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"已经连接" message:[NSString stringWithFormat:@"现在连接 %@了!", peer.displayName] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil nil];  
  661.             [alertView show];  
  662.         }  
  663.     }];  
  664.       
  665.     // 发正常数据的返回  
  666.     [self.sessionManager receiveDataOnMainQueue:YES block:^(NSData *data, MCPeerID *peer) {  
  667.          
  668.         __strong typeof (weakSelf) strongSelf = weakSelf;  
  669.           
  670.         NSString *string = [NSKeyedUnarchiver unarchiveObjectWithData:data];  
  671.           
  672.           
  673.         ChatItem * chatItem = [[ChatItem alloc] init];  
  674.         chatItem.isSelf = NO;  
  675.         chatItem.states = textStates;  
  676.         chatItem.content = string;  
  677.         [strongSelf.datasource addObject:chatItem];  
  678.         // 加到数组里面  
  679.           
  680.         [strongSelf insertTheTableToButtom];  
  681.           
  682.           
  683.     }];  
  684.       
  685.     // 发图片之后的返回  
  686.     [self.sessionManager receiveFinalResourceOnMainQueue:YES complete:^(NSString *name, MCPeerID *peer, NSURL *url, NSError *error) {  
  687.           
  688.         __strong typeof (weakSelf) strongSelf = weakSelf;  
  689.         NSData *data = [NSData dataWithContentsOfURL:url];  
  690.           
  691.         ChatItem * chatItem = [[ChatItem alloc] init];  
  692.         chatItem.isSelf = NO;  
  693.         chatItem.states = picStates;  
  694.         chatItem.content = name;  
  695.         chatItem.picImage = [UIImage imageWithData:data];  
  696.         [strongSelf.datasource addObject:chatItem];  
  697.         [strongSelf insertTheTableToButtom];  
  698.           
  699.     }];  
  700.       
  701.       
  702.       
  703.     // 流  
  704.     [self.sessionManager didReceiveStreamFromPeer:^(NSInputStream *stream, MCPeerID *peer, NSString *streamName) {  
  705.         __strong typeof (weakSelf) strongSelf = weakSelf;  
  706.         strongSelf.inputStream = stream;  
  707.         strongSelf.inputStream.delegate = self;  
  708.         [strongSelf.inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];  
  709.         [strongSelf.inputStream open];  
  710.           
  711.         NSLog(@"we need");  
  712.           
  713.     }];  
  714.       
  715. }  
  716. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex  
  717. {  
  718.     [self.sessionManager connectToPeer:buttonIndex == 1];  
  719. }  
  720.   
  721.   
  722.   
  723.   
  724.   
  725. #pragma mark 下面是流的传输  
  726.   
  727. /***********--------------------- 下面是流的传输 ------------------------***********************************/  
  728.   
  729. - (void)videoRecord  
  730. {  
  731.     // 播放录音  
  732.     [self SetTempRecordView];  
  733. }  
  734.   
  735.   
  736. - (void)sendAsStream  
  737. {  
  738.     if(!self.sessionManager.isConnected)  
  739.     {  
  740.         UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"蓝牙已经断开了,请重新连接!" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil nil];  
  741.         [alertView show];  
  742.         return;  
  743.     }  
  744.      
  745.     NSError *err;  
  746.     self.outputStream = [self.sessionManager streamWithName:@"super stream" toPeer:self.sessionManager.firstPeer error:&err];  
  747.     self.outputStream.delegate = self;  
  748.     [self.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];  
  749.     if(err || !self.outputStream) {  
  750.         NSLog(@"%@", err);  
  751.     }  
  752.     else  
  753.     {  
  754.           
  755.         [self.outputStream open];  
  756.     }  
  757. }  
  758.   
  759. // 下面是一个代理  
  760. - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode  
  761. {  
  762.      
  763.     if(eventCode == NSStreamEventHasBytesAvailable)  
  764.     {  
  765.          // 有可读的字节,接收到了数据  
  766.         NSInputStream *input = (NSInputStream *)aStream;  
  767.         uint8_t buffer[1024];  
  768.         NSInteger length = [input read:buffer maxLength:1024];  
  769.         [self.streamData appendBytes:(const voidvoid *)buffer length:(NSUInteger)length];  
  770.        // 记住这边的数据陆陆续续的  
  771.     }  
  772.     else if(eventCode == NSStreamEventHasSpaceAvailable)  
  773.     {  
  774.         // 可以使用输出流的空间,此时可以发送数据给服务器  
  775.         // 发送数据的  
  776.         NSData *data = [self getVideoStremData];  
  777.         ChatItem * chatItem = [[ChatItem alloc] init];  
  778.         chatItem.isSelf = YES;  
  779.         chatItem.states = videoStates;  
  780.         chatItem.recordData = data;  
  781.           
  782.         [self.datasource addObject:chatItem];  
  783.         [self insertTheTableToButtom];  
  784.           
  785.         NSOutputStream *output = (NSOutputStream *)aStream;  
  786.         [output write:data.bytes maxLength:data.length];  
  787.         [output close];  
  788.     }  
  789.     if(eventCode == NSStreamEventEndEncountered)  
  790.     {  
  791.         // 流结束事件,在此事件中负责做销毁工作  
  792.         // 同时也是获得最终数据的好地方  
  793.           
  794.         ChatItem * chatItem = [[ChatItem alloc] init];  
  795.         chatItem.isSelf = NO;  
  796.         chatItem.states = videoStates;  
  797.         chatItem.recordData = self.streamData;  
  798.           
  799.         [self.datasource addObject:chatItem];  
  800.         [self insertTheTableToButtom];  
  801.           
  802.         [aStream close];  
  803.         [aStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];  
  804.         if([aStream isKindOfClass:[NSInputStream class]])  
  805.         {  
  806.             self.streamData = nil;  
  807.         }  
  808.           
  809.     }  
  810.     if(eventCode == NSStreamEventErrorOccurred)  
  811.     {  
  812.         // 发生错误  
  813.         NSLog(@"error");  
  814.     }  
  815. }  
  816.   
  817. - (NSMutableData *)streamData  
  818. {  
  819.     if(!_streamData) {  
  820.         _streamData = [NSMutableData data];  
  821.     }  
  822.     return _streamData;  
  823. }  
  824.   
  825. /***********-----------------------  公用的数据 --------------------***********************************/  
  826.   
  827. - (NSData *)imageData  
  828. {  
  829.     return [NSData dataWithContentsOfURL:[self imageURL]];  
  830. }  
  831.   
  832. - (NSURL *)imageURL {  
  833.     NSString *path = [[NSBundle mainBundle]pathForResource:@"301-alien-ship@2x" ofType:@"png"];  
  834.     // 这儿有个技术点  
  835.     // 那个如何将 image转化成 路径  
  836.      
  837.     NSURL *url = [NSURL fileURLWithPath:path];  
  838.     return url;  
  839. }  
  840.   
  841. /***********----------------------------------------------***********************************/  
  842. #pragma mark 尝试空白处的连接  
  843.   
  844. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event  
  845. {  
  846.     UITouch * touch = [[event allTouches] anyObject];  
  847.     if(touch.tapCount >= 1)  
  848.     {  
  849.         [self.sendTextView resignFirstResponder];  
  850.     }  
  851. }  
  852.   
  853.   
  854. /***********-------------------语音---------------------------***********************************/  
  855.   
  856. #pragma mark 尝试语音的录制和播出  
  857.   
  858. - (void)buildVideoForWe  
  859. {  
  860.     // 设置录音会话  
  861.     [self setAudioSession];  
  862. }  
  863.   
  864. - (void)SetTempRecordView  
  865. {  
  866.     _backRemindRecordView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, 150)];  
  867.     _backRemindRecordView.center = self.view.center;  
  868.     _backRemindRecordView.backgroundColor = [UIColor lightGrayColor];  
  869.     [self.view addSubview:_backRemindRecordView];  
  870.       
  871.       
  872.     UILabel * beginLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 50, WIDTH -120, 50)];  
  873.     beginLabel.backgroundColor = [UIColor greenColor];  
  874.     beginLabel.text = @"长按录音开始···";  
  875.     beginLabel.tag = 1001;  
  876.     beginLabel.textAlignment = NSTextAlignmentCenter;  
  877.     beginLabel.userInteractionEnabled = YES;  
  878.     [_backRemindRecordView addSubview:beginLabel];  
  879.       
  880.     UILongPressGestureRecognizer * longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressNextDo:)];  
  881.     [beginLabel addGestureRecognizer:longPress];  
  882.       
  883.   
  884.       
  885.       
  886.       
  887.       
  888. }  
  889.   
  890.   
  891.   
  892. - (void)longPressNextDo:(UILongPressGestureRecognizer * )longPress  
  893. {  
  894.     if(longPress.state == UIGestureRecognizerStateBegan)  
  895.     {  
  896.         NSLog(@"begin");  
  897.         UILabel * label = (UILabel *)[_backRemindRecordView viewWithTag:1001];  
  898.         label.text = @"录音正在进行中···";  
  899.         label.backgroundColor = [UIColor orangeColor];  
  900.         [self BeginRecordClick];  
  901.     }  
  902.     if(longPress.state == UIGestureRecognizerStateEnded)  
  903.     {  
  904.         [self OkStopClick];  
  905.         [_backRemindRecordView removeFromSuperview];  
  906.         [self  sendAsStream];  
  907.         NSLog(@"stop");  
  908.          
  909.     }  
  910. }  
  911.   
  912.   
  913. #pragma mark - 私有方法  
  914. /** 
  915.  *  设置音频会话 
  916.  */  
  917. -(void)setAudioSession  
  918. {  
  919.     AVAudioSession *audioSession=[AVAudioSession sharedInstance];  
  920.     //设置为播放和录音状态,以便可以在录制完之后播放录音  
  921.     [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];  
  922.     [audioSession setActive:YES error:nil];  
  923. }  
  924.   
  925. /** 
  926.  *  取得录音文件保存路径 
  927.  * 
  928.  *  @return 录音文件路径 
  929.  */  
  930. -(NSURL *)getSavePath  
  931. {  
  932.     NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];  
  933.     urlStr=[urlStr stringByAppendingPathComponent:kRecordAudioFile];  
  934.     NSLog(@"file path:%@",urlStr);  
  935.     NSURL *url=[NSURL fileURLWithPath:urlStr];  
  936.     return url;  
  937. }  
  938.   
  939. - (NSData *)getVideoStremData  
  940. {  
  941.     return [NSData dataWithContentsOfURL:[self getSavePath]];  
  942. }  
  943.   
  944.   
  945. /** 
  946.  *  取得录音文件设置 
  947.  * 
  948.  *  @return 录音设置 
  949.  */  
  950. -(NSDictionary *)getAudioSetting{  
  951.     NSMutableDictionary *dicM=[NSMutableDictionary dictionary];  
  952.     //设置录音格式  
  953.     [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];  
  954.     //设置录音采样率,8000是电话采样率,对于一般录音已经够了  
  955.     [dicM setObject:@(8000) forKey:AVSampleRateKey];  
  956.     //设置通道,这里采用单声道  
  957.     [dicM setObject:@(1) forKey:AVNumberOfChannelsKey];  
  958.     //每个采样点位数,分为8、16、24、32  
  959.     [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];  
  960.     //是否使用浮点数采样  
  961.     [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];  
  962.     //....其他设置等  
  963.     return dicM;  
  964. }  
  965.   
  966. /** 
  967.  *  获得录音机对象 
  968.  * 
  969.  *  @return 录音机对象 
  970.  */  
  971. -(AVAudioRecorder *)audioRecorder  
  972. {  
  973.     if (!_audioRecorder) {  
  974.         //创建录音文件保存路径  
  975.         NSURL *url=[self getSavePath];  
  976.         //创建录音格式设置  
  977.         NSDictionary *setting=[self getAudioSetting];  
  978.         //创建录音机  
  979.         NSError *error=nil;  
  980.         _audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];  
  981.         _audioRecorder.delegate=self;  
  982.         _audioRecorder.meteringEnabled=YES;//如果要监控声波则必须设置为YES  
  983.         if (error) {  
  984.             NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);  
  985.             return nil;  
  986.         }  
  987.     }  
  988.     return _audioRecorder;  
  989. }  
  990.   
  991. /** 
  992.  *  创建播放器 
  993.  * 
  994.  *  @return 播放器 
  995.  */  
  996.   
  997.   
  998. - (void)makeVideoPlayer:(NSData *)data  
  999. {  
  1000.     NSError *error=nil;  
  1001.     self.audioPlayer=[[AVAudioPlayer alloc]initWithData:data error:&error];  
  1002.     self.audioPlayer.delegate = self;  
  1003.     self.audioPlayer.numberOfLoops=0;  
  1004.     [self.audioPlayer prepareToPlay];  
  1005.     if (error)  
  1006.     {  
  1007.         NSLog(@"创建播放器过程中发生错误,错误信息:%@",error.localizedDescription);  
  1008.          
  1009.     }  
  1010.     else  
  1011.     {  
  1012.         if (![self.audioPlayer isPlaying]) {  
  1013.             NSLog(@"play");  
  1014.                 [self.audioPlayer play];  
  1015.         }  
  1016.           
  1017.     }  
  1018. }  
  1019.   
  1020.   
  1021.   
  1022.   
  1023.   
  1024. /** 
  1025.  *  录音声波监控定制器 
  1026.  * 
  1027.  *  @return 定时器 
  1028.  */  
  1029. -(NSTimer *)timer{  
  1030.     if (!_timer) {  
  1031.         _timer=[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(audioPowerChange) userInfo:nil repeats:YES];  
  1032.     }  
  1033.     return _timer;  
  1034. }  
  1035.   
  1036. /** 
  1037.  *  录音声波状态设置 
  1038.  */  
  1039. -(void)audioPowerChange{  
  1040.     [self.audioRecorder updateMeters];//更新测量值  
  1041.     float power= [self.audioRecorder averagePowerForChannel:0];//取得第一个通道的音频,注意音频强度范围时-160到0  
  1042.     CGFloat progress=(1.0/160.0)*(power+160.0);  
  1043.     [self.audioPower setProgress:progress];  
  1044. }  
  1045. #pragma mark - UI事件  
  1046. /** 
  1047.  *  点击录音按钮 
  1048.  * 
  1049.  *  @param sender 录音按钮 
  1050.  */  
  1051. - (void)BeginRecordClick  
  1052. {  
  1053.     if (![self.audioRecorder isRecording])  
  1054.     {  
  1055.         [self.audioRecorder record];//首次使用应用时如果调用record方法会询问用户是否允许使用麦克风  
  1056.         self.timer.fireDate=[NSDate distantPast];  
  1057.     }  
  1058. }  
  1059.   
  1060. /** 
  1061.  *  点击暂定按钮 
  1062.  * 
  1063.  *  @param sender 暂停按钮 
  1064.  */  
  1065. - (void)StopPauseClick  
  1066. {  
  1067.     if ([self.audioRecorder isRecording]) {  
  1068.         [self.audioRecorder pause];  
  1069.         self.timer.fireDate=[NSDate distantFuture];  
  1070.     }  
  1071. }  
  1072.   
  1073.   
  1074. /** 
  1075.  *  点击停止按钮 
  1076.  * 
  1077.  *  @param sender 停止按钮 
  1078.  */  
  1079. - (void)OkStopClick  
  1080. {  
  1081.     [self.audioRecorder stop];  
  1082.     self.timer.fireDate=[NSDate distantFuture];  
  1083.     self.audioPower.progress=0.0;  
  1084. }  
  1085.   
  1086. #pragma mark - 录音机代理方法  
  1087. /** 
  1088.  *  录音完成,录音完成后播放录音 
  1089.  * 
  1090.  *  @param recorder 录音机对象 
  1091.  *  @param flag     是否成功 
  1092.  */  
  1093. -(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag  
  1094. {  
  1095. //    if (![self.audioPlayer isPlaying]) {  
  1096. //        [self.audioPlayer play];  
  1097. //    }  
  1098.     NSLog(@"录音完成!");  
  1099. }  
  1100.   
  1101. - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag  
  1102. {  
  1103.       
  1104.     // 每次完成后都将这个对象释放  
  1105.     player =nil;  
  1106. }  

建一个model类:

[objc] view plain copy

  1. .h  
  2. #import <UIKit/UIKit.h>  
  3. //@protocol CellSelectIndex <NSObject>  
  4. //  
  5. //- (void)cellSelectIndex;  
  6. //  
  7. //@end  
  8.   
  9.   
  10. @interface ChatCell : UITableViewCell  
  11. @property(nonatomic,strong)UIImageView * lefeView;  
  12. @property(nonatomic,strong)UIImageView * rightView;  
  13. @property(nonatomic,strong)UILabel * leftLabel;  
  14. @property(nonatomic,strong)UILabel * rightLabel;  
  15.   
  16. @property(nonatomic,strong)UIImageView * leftHeadImage;  
  17. @property(nonatomic,strong)UIImageView * rightHeadImage;  
  18.   
  19. @property(nonatomic,strong)UIImageView * leftPicImage;  
  20. @property(nonatomic,strong)UIImageView * rightPicImage;  
  21.   
  22.   
  23. @property(nonatomic ,strong)UIButton * leftVideoButton;  
  24. @property(nonatomic, strong)UIButton * rightVideoButton;  
  25.   
  26. //@property(nonatomic,weak)id <CellSelectIndex> delegate;  
  27.   
  28. // 不能用名字相同的属性  
  29. //  记住自动的时候,讲一下 weak  and strong   
  30.   
  31. @end  
  32.   
  33.   
  34. .m  
  35. #import "ChatCell.h"  
  36.   
  37. @implementation ChatCell  
  38.   
  39. - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier  
  40. {  
  41.     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];  
  42.     if (self) {  
  43.         // Initialization code  
  44.         [self makeView];  
  45.     }  
  46.     return self;  
  47. }  
  48. -(void)makeView  
  49. {  
  50.     UIImage * leftImgae = [UIImage imageNamed:@"ReceiverTextNodeBkg.png"];  
  51.     UIImage * rightImage = [UIImage imageNamed:@"SenderTextNodeBkg.png"];  
  52.       
  53.     //这里设定一行一像素 当图片拉伸的时候,只放大两个像素  
  54.       
  55.     leftImgae = [leftImgae stretchableImageWithLeftCapWidth:30 topCapHeight:35];  
  56.     // 找一行一列的像素  
  57.     rightImage = [rightImage stretchableImageWithLeftCapWidth:30 topCapHeight:35];  
  58.     // 设定完了后生成了一个新的image;  
  59.       
  60. //----------------------------------------------------------------------------------------//  
  61.     // 左边头像  
  62.     self.leftHeadImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 30, 30)];  
  63.     self.leftHeadImage.layer.masksToBounds = YES;  
  64.     self.leftHeadImage.layer.cornerRadius = 12;  
  65.     self.leftHeadImage.image = [UIImage imageNamed:@"f-pCert.png"];  
  66.     [self.contentView addSubview:self.leftHeadImage];  
  67.       
  68.     //左边气泡  
  69.     self.leftVideoButton = [UIButton buttonWithType:UIButtonTypeCustom];  
  70.     self.leftVideoButton.frame = CGRectMake(40, 5, 35, 35);  
  71. //    [self.leftVideoButton addTarget:self action:@selector(recordTheVoice) forControlEvents:UIControlEventTouchUpInside];  
  72.     [self.contentView addSubview:self.leftVideoButton];  
  73.       
  74.     self.leftPicImage = [[UIImageView alloc] initWithFrame:CGRectMake(40, 5, 66, 30)];  
  75.     [self.contentView addSubview:self.leftPicImage];  
  76.       
  77.     self.lefeView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 5, 66, 30)];  
  78.     self.lefeView.image = leftImgae;  
  79.     // 这里不是一个小像素的图片??  
  80.     [self.contentView addSubview:self.lefeView];  
  81.       
  82.       
  83.     self.leftLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 5, 1, 1)];  
  84.     self.leftLabel.font = [UIFont systemFontOfSize:14];  
  85.       
  86.     self.leftLabel.numberOfLines = 0; // 换行  
  87.       
  88.     self.leftLabel.backgroundColor = [UIColor clearColor];// 设置透明的  
  89.       
  90.     [self.lefeView addSubview:self.leftLabel];  
  91.       
  92. //----------------------------------------------------------------------------------------//  
  93.       
  94.     self.rightHeadImage = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - 35, 5, 30, 30)];  
  95.     self.rightHeadImage.layer.masksToBounds = YES;  
  96.     self.rightHeadImage.layer.cornerRadius = 12;  
  97.     self.rightHeadImage.image = [UIImage imageNamed:@"f-plove.png"];  
  98.     [self.contentView addSubview:self.rightHeadImage];  
  99.       
  100.     self.rightVideoButton = [UIButton buttonWithType:UIButtonTypeCustom];  
  101.     self.rightVideoButton.frame = CGRectMake(self.frame.size.width - 45 - 40, 5, 35, 35);  
  102. //    [self.rightVideoButton addTarget:self action:@selector(recordTheVoice) forControlEvents:UIControlEventTouchUpInside];  
  103.     [self.contentView addSubview:self.rightVideoButton];  
  104.       
  105.     self.rightPicImage = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - 45 - 30, 5, 30, 30)];  
  106.     [self.contentView addSubview:self.rightPicImage];  
  107.       
  108.     // 右边  
  109.     self.rightView = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - (66+40), 5, 66, 30)];  
  110.     self.rightView.image = rightImage;  
  111.     [self.contentView addSubview:self.rightView];  
  112.   
  113.       
  114.     self.rightLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 1, 1)];  
  115.     self.rightLabel.font = [UIFont systemFontOfSize:14];  
  116.     self.rightLabel.backgroundColor = [UIColor clearColor];  
  117.     self.rightLabel.numberOfLines = 0;  
  118.     [self.rightView addSubview:self.rightLabel];  
  119.    
  120. }  
  121.   
  122. //- (void)recordTheVoice  
  123. //{  
  124. //    [self.delegate cellSelectIndex];  
  125. //}  

每日更新关注:http://weibo.com/hanjunqiang  新浪微博

 基本知识必须了解的

 MCAdvertiserAssistant   //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。

 MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。

 MCNearbyServiceBrowser  //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。

 MCPeerID //这表明是一个用户

 MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。

建一个类用来写所有方法:

[objc] view plain copy

  1. .h  
  2. #import <Foundation/Foundation.h>  
  3.   
  4. @import MultipeerConnectivity;  
  5.   
  6. @interface BlueSessionManager : NSObject  
  7.   
  8. @property(strong, nonatomic, readonly) NSArray *connectedPeers;  
  9.   
  10. @property(strong, nonatomic, readonly) MCSession *session;  
  11.   
  12. @property(nonatomic, readonly, getter = isConnected) BOOL connected;  
  13.   
  14. @property(strong, nonatomic) NSDictionary *discoveryInfo; // 发现设备的特征  
  15.   
  16. @property(strong, nonatomic, readonly) MCPeerID *firstPeer; // 第一个连接的 用户  
  17.   
  18. /** 
  19.  * The service type provided for browsing and advertising. 
  20.  * This should be a short text string that describes the 
  21.  * app's networking protocol. Should be something 
  22.  * in the form of `tjl_appname`. 
  23.  */  
  24. @property(strong, nonatomic) NSString *serviceType;  
  25.   
  26.   
  27. /* 
  28.  初始化一个 假设的用户名字 
  29.  */  
  30. - (instancetype)__attribute__((nonnull(1)))initWithDisplayName:(NSString *)displayName;  
  31.   
  32.   
  33. - (void)browseForProgrammaticDiscovery;  
  34.   
  35.   
  36. - (void)advertiseForBrowserViewController;  
  37.   
  38.   
  39. - (void)advertiseForProgrammaticDiscovery;  
  40.   
  41. - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;  
  42.   
  43.   
  44. - (NSError *)sendDataToAllPeers:(NSData *)data;  
  45. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers;  
  46.   
  47.   
  48. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode;  
  49.   
  50.   
  51. - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock;  
  52.   
  53.   
  54. - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete;  
  55.   
  56.   
  57. - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block;  
  58.   
  59.   
  60. - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block;  
  61.   
  62.   
  63. - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error;  
  64.   
  65.   
  66. - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock;  
  67.   
  68. - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status;  
  69.   
  70.   
  71. - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled;  
  72.   
  73.   
  74. - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found;  
  75. - (void)connectToPeer:(BOOL)connect;  
  76.   
  77. // 邀请其他设备连接  
  78. - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected;  
  79. - (void)disconnectSession;  
  80. // 停止打开自己  
  81. - (void)stopAdvertising;  
  82.   
  83. // 停止扫描  
  84. - (void)stopBrowsing;  
  85.   
  86. @end  
  87.   
  88.   
  89.   
  90.   
  91. .m  
  92. #import "BlueSessionManager.h"  
  93.   
  94. #define ServiceType @"MyService"  
  95.   
  96. /* 
  97.  MCAdvertiserAssistant   //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。 
  98.  MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。 
  99.  MCNearbyServiceBrowser  //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。 
  100.  MCPeerID //这表明是一个用户 
  101.  MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。 
  102.  */  
  103. @interface BlueSessionManager ()<MCAdvertiserAssistantDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate, MCNearbyServiceAdvertiserDelegate, UIAlertViewDelegate>  
  104. @property(strong, nonatomic) MCSession *currentSession; // 当前会议  
  105. @property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣传助手  
  106. @property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服务助手  
  107. @property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索蓝牙者  
  108. @property(strong, nonatomic) MCPeerID *peerID; // 用户  
  109.   
  110. //  以下都是用到的block  
  111. @property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);  
  112. @property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);  
  113. @property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);  
  114. @property(nonatomic, copy) void(^browserConnected)(void);  
  115. @property(nonatomic, copy) void(^browserCancelled)(void);  
  116. @property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);  
  117. @property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);  
  118. @property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);  
  119. @property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);  
  120. @property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);  
  121. @property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);  
  122. // 各种判断  
  123. @property(nonatomic, assign) BOOL receiveOnMainQueue;  
  124. @property(nonatomic, assign) BOOL statusOnMainQueue;  
  125. @property(nonatomic, assign) BOOL resourceFinalOnMainQueue;  
  126. @property(nonatomic, assign) BOOL resourceStart;  
  127. @end  
  128. @implementation BlueSessionManager  
  129. #pragma mark 初始化自己  
  130. - (instancetype)initWithDisplayName:(NSString *)displayName  
  131. {  
  132.     return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];  
  133. }  
  134. // 为上面自定义 用户  
  135. - (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type  
  136. {  
  137.     self = [super init];  
  138.     if(!self) {  
  139.         return nil;  
  140.     }  
  141.     self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];  
  142.     self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];  
  143.     self.session.delegate = self;  
  144.     self.serviceType = type;  
  145.     return self;  
  146. }  
  147. #pragma mark 宣传自己  
  148. - (void)advertiseForBrowserViewController  
  149. {  
  150.     [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];  
  151. }  
  152.   
  153. - (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info  
  154. {  
  155.     //  
  156.     self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];  
  157.     self.advertiser.delegate = self;  
  158.     [self.advertiser startAdvertisingPeer];  
  159. }  
  160.   
  161. - (void)advertiseForProgrammaticDiscovery  
  162. {  
  163.     [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];  
  164. }  
  165.   
  166. - (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info  
  167. {  
  168.     //自定义自己,为了让其他设备搜索到自己  
  169.     self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];  
  170.     self.advertisingAssistant.delegate = self;  
  171.     [self.advertisingAssistant start];  
  172. }  
  173.   
  174. - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {  
  175.     self.invitationHandler = [invitationHandler copy];  
  176.     if(self.inviteBlock) self.inviteBlock(peerID, context);  
  177. }  
  178.   
  179. #pragma mark 下面是MCAdvertiserAssistant的两个代理  
  180. - (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant  
  181. {  
  182.     //TODO implement  
  183. }  
  184.   
  185. - (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {  
  186.     //TODO implement  
  187. }  
  188.   
  189. #pragma mark  扫描其他的设备  
  190. - (void)browseForProgrammaticDiscovery  
  191. {  
  192.       
  193.     self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];  
  194.     self.browser.delegate = self;  
  195.     [self.browser startBrowsingForPeers];  
  196.       
  197. }  
  198.   
  199. #pragma mark MCNearbyServiceBrowserDelegate   
  200. - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID  
  201. {  
  202.     //TODO implement  
  203. }  
  204.   
  205. - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info  
  206. {  
  207.     if(self.didFindPeer)  
  208.     {  
  209.         self.didFindPeer(peerID, info);  
  210.     }  
  211. }  
  212.   
  213. - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error  
  214. {  
  215.     //TODO implement  
  216. }  
  217.   
  218. #pragma mark 参加会议  也是会议的代理  
  219. //   也是  ----- MCSessionDelegate  
  220.   
  221. //  这是完成会议的结果···  
  222. - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error  
  223. {  
  224.       if(self.resourceFinalOnMainQueue)  
  225.     {  
  226.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  227.             if(self.finalResource)  
  228.             {  
  229.                 self.finalResource(resourceName, peerID, localURL, error);  
  230.             }  
  231.         }];  
  232.     }  
  233.     else  
  234.     {  
  235.         if(self.finalResource)  
  236.         {  
  237.             self.finalResource(resourceName, peerID, localURL, error);  
  238.         }  
  239.     }  
  240. }  
  241. // 这是参加  普通数据的会议  
  242. - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID  
  243. {  
  244.     if(self.receiveOnMainQueue)  
  245.     {  
  246.     [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  247.      if(self.receiveDataBlock){  
  248.         self.receiveDataBlock(data, peerID);  
  249.             }  
  250.         }];  
  251.     }  
  252.     else  
  253.     {  
  254.         if(self.receiveDataBlock)  
  255.         {  
  256.             self.receiveDataBlock(data, peerID);  
  257.         }  
  258.     }  
  259. }  
  260. // 这是参加普通流的会议  
  261. - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID  
  262. {  
  263.      if(self.streamBlock)  
  264.     {  
  265.         self.streamBlock(stream, peerID, streamName);  
  266.     }  
  267. }  
  268. // 这是参加图片资源的会议  
  269. - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress  
  270. {  
  271.     if(self.resourceStart)  
  272.     {  
  273.           
  274.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  275.             if(self.didStartReceivingResource)  
  276.             {  
  277.                 self.didStartReceivingResource(resourceName, peerID, progress);  
  278.             }  
  279.         }];  
  280.     }  
  281.     else  
  282.     {  
  283.         
  284.         if(self.didStartReceivingResource)  
  285.         {  
  286.             self.didStartReceivingResource(resourceName, peerID, progress);  
  287.         }  
  288.     }  
  289. }  
  290.   
  291.   
  292. // 这是不同数据,系那是不同会议时候的状态  
  293.   
  294. - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state  
  295. {  
  296.     // 这个地方是当两个蓝牙设备一旦连接起来,就会形成的一个会议  
  297.     if(self.statusOnMainQueue)  
  298.     {  
  299.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  300.             if(self.connectionStatus)  
  301.             {  
  302.                 self.connectionStatus(peerID, state);  
  303.             }  
  304.         }];  
  305.     }  
  306.     else  
  307.     {  
  308.         if(self.connectionStatus)  
  309.         {  
  310.             self.connectionStatus(peerID, state);  
  311.         }  
  312.     }  
  313. }  
  314.   
  315.   
  316.   
  317. #pragma mark  send And receive  
  318. //--------------------------------------------------------------------------------------------//  
  319. // 发送消息  
  320. // 用户多个  
  321. - (NSError *)sendDataToAllPeers:(NSData *)data  
  322. {  
  323.     // 普通数据的发送  
  324.     return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];  
  325. }  
  326.   
  327. - (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode  
  328. {  
  329.     // 确实进入会议  
  330.     NSError *error;  
  331.     [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];  
  332.     return error;  
  333. }  
  334.   
  335. // 用户确定一个  
  336. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers  
  337. {  
  338.     return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];  
  339. }  
  340.   
  341. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode  
  342. {  
  343.     NSError *error;  
  344.     [self.session sendData:data toPeers:peers withMode:mode error:&error];  
  345.     return error;  
  346. }  
  347.   
  348.   
  349. // 接收消息  
  350. - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock  
  351. {  
  352.       
  353.     self.receiveDataBlock = [dataBlock copy];  
  354.     self.receiveOnMainQueue = mainQueue;  
  355. }  
  356. //--------------------------------------------------------------------------------------------//  
  357.   
  358. - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete  
  359. {  
  360.     // 图片资源数据的发送  
  361.       
  362.     return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];  
  363. }  
  364.   
  365. // 用户连接确定   
  366. - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status  
  367. {  
  368.     self.connectionStatus = [status copy];  
  369.     self.statusOnMainQueue = mainQueue;  
  370. }  
  371.   
  372.   
  373. #pragma mark 自带的MCBrowserViewController类  
  374. - (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController  
  375. {  
  376.     [browserViewController dismissViewControllerAnimated:YES completion:^{  
  377.         if(self.browserConnected) self.browserConnected();  
  378.     }];  
  379. }  
  380.   
  381. - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController  
  382. {  
  383.     [browserViewController dismissViewControllerAnimated:YES completion:^{  
  384.         if(self.browserCancelled) self.browserCancelled();  
  385.     }];  
  386. }  
  387.   
  388. - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled  
  389. {  
  390.     self.browserConnected = [connected copy];  
  391.     self.browserCancelled = [cancelled copy];  
  392.     // 注意这个自带的类  
  393.     MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];  
  394.     browser.delegate = self;  
  395.     [controller presentViewController:browser animated:YES completion:nil];  
  396. }  
  397.   
  398. - (NSArray *)connectedPeers  
  399. {  
  400.     return self.session.connectedPeers;  
  401. }  
  402.   
  403. // 邀请某某连接  
  404. - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;  
  405. {  
  406.     self.inviteBlock = [invite copy];  
  407. }  
  408.   
  409. - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected  
  410. {  
  411.     [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];  
  412. }  
  413.   
  414. - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block  
  415. {  
  416.       
  417.     self.didStartReceivingResource = [block copy];  
  418.     self.resourceStart = mainQueue;  
  419. }  
  420. // 接收某某资源  
  421. - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block  
  422. {  
  423.     self.finalResource = [block copy];  
  424.     self.resourceFinalOnMainQueue = mainQueue;  
  425. }  
  426. - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error  
  427. {  
  428.     return [self.session startStreamWithName:name toPeer:peerID error:error];  
  429. }  
  430. // 开始转化为流  
  431. - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock  
  432. {  
  433.     self.streamBlock = [streamBlock copy];  
  434. }  
  435. - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found  
  436. {  
  437.     self.didFindPeer = [found copy];  
  438. }  
  439. #pragma mark  一些断开的情况  
  440. - (void)disconnectSession  
  441. {  
  442.     [self.session disconnect];  
  443. }  
  444.   
  445. - (void)stopAdvertising  
  446. {  
  447.     [self.advertiser stopAdvertisingPeer];  
  448.     [self.advertisingAssistant stop];  
  449. }  
  450.   
  451. - (void)stopBrowsing  
  452. {  
  453.     [self.browser stopBrowsingForPeers];  
  454. }  
  455.   
  456. - (BOOL)isConnected {  
  457.     return self.session.connectedPeers && self.session.connectedPeers.count > 0;  
  458. }  
  459.   
  460. // 是否连接 它  
  461. - (void)connectToPeer:(BOOL)connect {  
  462.     self.invitationHandler(connect, self.session);  
  463. }  
  464.   
  465. - (MCSession *)session {  
  466.     return self.currentSession;  
  467. }  
  468.   
  469. - (MCPeerID *)firstPeer {  
  470.     return self.session.connectedPeers.firstObject;  
  471. }  
  472.   
  473. @end  
  474.   
  475. #import "BlueSessionManager.h"  
  476.   
  477. #define ServiceType @"MyService"  
  478.   
  479. /* 
  480.  MCAdvertiserAssistant   //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。 
  481.  MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。 
  482.  MCNearbyServiceBrowser  //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。 
  483.  MCPeerID //这表明是一个用户 
  484.  MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。 
  485.  */  
  486. @interface BlueSessionManager ()<MCAdvertiserAssistantDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate, MCNearbyServiceAdvertiserDelegate, UIAlertViewDelegate>  
  487. @property(strong, nonatomic) MCSession *currentSession; // 当前会议  
  488. @property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣传助手  
  489. @property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服务助手  
  490. @property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索蓝牙者  
  491. @property(strong, nonatomic) MCPeerID *peerID; // 用户  
  492.   
  493. //  以下都是用到的block  
  494. @property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);  
  495. @property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);  
  496. @property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);  
  497. @property(nonatomic, copy) void(^browserConnected)(void);  
  498. @property(nonatomic, copy) void(^browserCancelled)(void);  
  499. @property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);  
  500. @property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);  
  501. @property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);  
  502. @property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);  
  503. @property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);  
  504. @property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);  
  505. // 各种判断  
  506. @property(nonatomic, assign) BOOL receiveOnMainQueue;  
  507. @property(nonatomic, assign) BOOL statusOnMainQueue;  
  508. @property(nonatomic, assign) BOOL resourceFinalOnMainQueue;  
  509. @property(nonatomic, assign) BOOL resourceStart;  
  510. @end  
  511. @implementation BlueSessionManager  
  512. #pragma mark 初始化自己  
  513. - (instancetype)initWithDisplayName:(NSString *)displayName  
  514. {  
  515.     return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];  
  516. }  
  517. // 为上面自定义 用户  
  518. - (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type  
  519. {  
  520.     self = [super init];  
  521.     if(!self) {  
  522.         return nil;  
  523.     }  
  524.     self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];  
  525.     self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];  
  526.     self.session.delegate = self;  
  527.     self.serviceType = type;  
  528.     return self;  
  529. }  
  530. #pragma mark 宣传自己  
  531. - (void)advertiseForBrowserViewController  
  532. {  
  533.     [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];  
  534. }  
  535.   
  536. - (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info  
  537. {  
  538.     //  
  539.     self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];  
  540.     self.advertiser.delegate = self;  
  541.     [self.advertiser startAdvertisingPeer];  
  542. }  
  543.   
  544. - (void)advertiseForProgrammaticDiscovery  
  545. {  
  546.     [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];  
  547. }  
  548.   
  549. - (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info  
  550. {  
  551.     //自定义自己,为了让其他设备搜索到自己  
  552.     self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];  
  553.     self.advertisingAssistant.delegate = self;  
  554.     [self.advertisingAssistant start];  
  555. }  
  556.   
  557. - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {  
  558.     self.invitationHandler = [invitationHandler copy];  
  559.     if(self.inviteBlock) self.inviteBlock(peerID, context);  
  560. }  
  561.   
  562. #pragma mark 下面是MCAdvertiserAssistant的两个代理  
  563. - (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant  
  564. {  
  565.     //TODO implement  
  566. }  
  567.   
  568. - (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {  
  569.     //TODO implement  
  570. }  
  571.   
  572. #pragma mark  扫描其他的设备  
  573. - (void)browseForProgrammaticDiscovery  
  574. {  
  575.       
  576.     self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];  
  577.     self.browser.delegate = self;  
  578.     [self.browser startBrowsingForPeers];  
  579.       
  580. }  
  581.   
  582. #pragma mark MCNearbyServiceBrowserDelegate   
  583. - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID  
  584. {  
  585.     //TODO implement  
  586. }  
  587.   
  588. - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info  
  589. {  
  590.     if(self.didFindPeer)  
  591.     {  
  592.         self.didFindPeer(peerID, info);  
  593.     }  
  594. }  
  595.   
  596. - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error  
  597. {  
  598.     //TODO implement  
  599. }  
  600.   
  601. #pragma mark 参加会议  也是会议的代理  
  602. //   也是  ----- MCSessionDelegate  
  603.   
  604. //  这是完成会议的结果···  
  605. - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error  
  606. {  
  607.       if(self.resourceFinalOnMainQueue)  
  608.     {  
  609.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  610.             if(self.finalResource)  
  611.             {  
  612.                 self.finalResource(resourceName, peerID, localURL, error);  
  613.             }  
  614.         }];  
  615.     }  
  616.     else  
  617.     {  
  618.         if(self.finalResource)  
  619.         {  
  620.             self.finalResource(resourceName, peerID, localURL, error);  
  621.         }  
  622.     }  
  623. }  
  624. // 这是参加  普通数据的会议  
  625. - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID  
  626. {  
  627.     if(self.receiveOnMainQueue)  
  628.     {  
  629.     [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  630.      if(self.receiveDataBlock){  
  631.         self.receiveDataBlock(data, peerID);  
  632.             }  
  633.         }];  
  634.     }  
  635.     else  
  636.     {  
  637.         if(self.receiveDataBlock)  
  638.         {  
  639.             self.receiveDataBlock(data, peerID);  
  640.         }  
  641.     }  
  642. }  
  643. // 这是参加普通流的会议  
  644. - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID  
  645. {  
  646.      if(self.streamBlock)  
  647.     {  
  648.         self.streamBlock(stream, peerID, streamName);  
  649.     }  
  650. }  
  651. // 这是参加图片资源的会议  
  652. - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress  
  653. {  
  654.     if(self.resourceStart)  
  655.     {  
  656.           
  657.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  658.             if(self.didStartReceivingResource)  
  659.             {  
  660.                 self.didStartReceivingResource(resourceName, peerID, progress);  
  661.             }  
  662.         }];  
  663.     }  
  664.     else  
  665.     {  
  666.         
  667.         if(self.didStartReceivingResource)  
  668.         {  
  669.             self.didStartReceivingResource(resourceName, peerID, progress);  
  670.         }  
  671.     }  
  672. }  
  673.   
  674.   
  675. // 这是不同数据,系那是不同会议时候的状态  
  676.   
  677. - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state  
  678. {  
  679.     // 这个地方是当两个蓝牙设备一旦连接起来,就会形成的一个会议  
  680.     if(self.statusOnMainQueue)  
  681.     {  
  682.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  683.             if(self.connectionStatus)  
  684.             {  
  685.                 self.connectionStatus(peerID, state);  
  686.             }  
  687.         }];  
  688.     }  
  689.     else  
  690.     {  
  691.         if(self.connectionStatus)  
  692.         {  
  693.             self.connectionStatus(peerID, state);  
  694.         }  
  695.     }  
  696. }  
  697.   
  698.   
  699.   
  700. #pragma mark  send And receive  
  701. //--------------------------------------------------------------------------------------------//  
  702. // 发送消息  
  703. // 用户多个  
  704. - (NSError *)sendDataToAllPeers:(NSData *)data  
  705. {  
  706.     // 普通数据的发送  
  707.     return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];  
  708. }  
  709.   
  710. - (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode  
  711. {  
  712.     // 确实进入会议  
  713.     NSError *error;  
  714.     [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];  
  715.     return error;  
  716. }  
  717.   
  718. // 用户确定一个  
  719. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers  
  720. {  
  721.     return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];  
  722. }  
  723.   
  724. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode  
  725. {  
  726.     NSError *error;  
  727.     [self.session sendData:data toPeers:peers withMode:mode error:&error];  
  728.     return error;  
  729. }  
  730.   
  731.   
  732. // 接收消息  
  733. - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock  
  734. {  
  735.       
  736.     self.receiveDataBlock = [dataBlock copy];  
  737.     self.receiveOnMainQueue = mainQueue;  
  738. }  
  739. //--------------------------------------------------------------------------------------------//  
  740.   
  741. - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete  
  742. {  
  743.     // 图片资源数据的发送  
  744.       
  745.     return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];  
  746. }  
  747.   
  748. // 用户连接确定   
  749. - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status  
  750. {  
  751.     self.connectionStatus = [status copy];  
  752.     self.statusOnMainQueue = mainQueue;  
  753. }  
  754.   
  755.   
  756. #pragma mark 自带的MCBrowserViewController类  
  757. - (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController  
  758. {  
  759.     [browserViewController dismissViewControllerAnimated:YES completion:^{  
  760.         if(self.browserConnected) self.browserConnected();  
  761.     }];  
  762. }  
  763.   
  764. - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController  
  765. {  
  766.     [browserViewController dismissViewControllerAnimated:YES completion:^{  
  767.         if(self.browserCancelled) self.browserCancelled();  
  768.     }];  
  769. }  
  770.   
  771. - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled  
  772. {  
  773.     self.browserConnected = [connected copy];  
  774.     self.browserCancelled = [cancelled copy];  
  775.     // 注意这个自带的类  
  776.     MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];  
  777.     browser.delegate = self;  
  778.     [controller presentViewController:browser animated:YES completion:nil];  
  779. }  
  780.   
  781. - (NSArray *)connectedPeers  
  782. {  
  783.     return self.session.connectedPeers;  
  784. }  
  785.   
  786. // 邀请某某连接  
  787. - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;  
  788. {  
  789.     self.inviteBlock = [invite copy];  
  790. }  
  791.   
  792. - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected  
  793. {  
  794.     [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];  
  795. }  
  796.   
  797. - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block  
  798. {  
  799.       
  800.     self.didStartReceivingResource = [block copy];  
  801.     self.resourceStart = mainQueue;  
  802. }  
  803. // 接收某某资源  
  804. - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block  
  805. {  
  806.     self.finalResource = [block copy];  
  807.     self.resourceFinalOnMainQueue = mainQueue;  
  808. }  
  809. - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error  
  810. {  
  811.     return [self.session startStreamWithName:name toPeer:peerID error:error];  
  812. }  
  813. // 开始转化为流  
  814. - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock  
  815. {  
  816.     self.streamBlock = [streamBlock copy];  
  817. }  
  818. - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found  
  819. {  
  820.     self.didFindPeer = [found copy];  
  821. }  
  822. #pragma mark  一些断开的情况  
  823. - (void)disconnectSession  
  824. {  
  825.     [self.session disconnect];  
  826. }  
  827.   
  828. - (void)stopAdvertising  
  829. {  
  830.     [self.advertiser stopAdvertisingPeer];  
  831.     [self.advertisingAssistant stop];  
  832. }  
  833.   
  834. - (void)stopBrowsing  
  835. {  
  836.     [self.browser stopBrowsingForPeers];  
  837. }  
  838.   
  839. - (BOOL)isConnected {  
  840.     return self.session.connectedPeers && self.session.connectedPeers.count > 0;  
  841. }  
  842.   
  843. // 是否连接 它  
  844. - (void)connectToPeer:(BOOL)connect {  
  845.     self.invitationHandler(connect, self.session);  
  846. }  
  847.   
  848. - (MCSession *)session {  
  849.     return self.currentSession;  
  850. }  
  851.   
  852. - (MCPeerID *)firstPeer {  
  853.     return self.session.connectedPeers.firstObject;  
  854. }  
  855.   
  856. @end  
  857.   
  858. #import "BlueSessionManager.h"  
  859.   
  860. #define ServiceType @"MyService"  
  861.   
  862. /* 
  863.  MCAdvertiserAssistant   //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。 
  864.  MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。 
  865.  MCNearbyServiceBrowser  //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。 
  866.  MCPeerID //这表明是一个用户 
  867.  MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。 
  868.  */  
  869. @interface BlueSessionManager ()<MCAdvertiserAssistantDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate, MCNearbyServiceAdvertiserDelegate, UIAlertViewDelegate>  
  870. @property(strong, nonatomic) MCSession *currentSession; // 当前会议  
  871. @property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣传助手  
  872. @property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服务助手  
  873. @property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索蓝牙者  
  874. @property(strong, nonatomic) MCPeerID *peerID; // 用户  
  875.   
  876. //  以下都是用到的block  
  877. @property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);  
  878. @property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);  
  879. @property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);  
  880. @property(nonatomic, copy) void(^browserConnected)(void);  
  881. @property(nonatomic, copy) void(^browserCancelled)(void);  
  882. @property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);  
  883. @property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);  
  884. @property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);  
  885. @property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);  
  886. @property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);  
  887. @property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);  
  888. // 各种判断  
  889. @property(nonatomic, assign) BOOL receiveOnMainQueue;  
  890. @property(nonatomic, assign) BOOL statusOnMainQueue;  
  891. @property(nonatomic, assign) BOOL resourceFinalOnMainQueue;  
  892. @property(nonatomic, assign) BOOL resourceStart;  
  893. @end  
  894. @implementation BlueSessionManager  
  895. #pragma mark 初始化自己  
  896. - (instancetype)initWithDisplayName:(NSString *)displayName  
  897. {  
  898.     return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];  
  899. }  
  900. // 为上面自定义 用户  
  901. - (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type  
  902. {  
  903.     self = [super init];  
  904.     if(!self) {  
  905.         return nil;  
  906.     }  
  907.     self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];  
  908.     self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];  
  909.     self.session.delegate = self;  
  910.     self.serviceType = type;  
  911.     return self;  
  912. }  
  913. #pragma mark 宣传自己  
  914. - (void)advertiseForBrowserViewController  
  915. {  
  916.     [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];  
  917. }  
  918.   
  919. - (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info  
  920. {  
  921.     //  
  922.     self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];  
  923.     self.advertiser.delegate = self;  
  924.     [self.advertiser startAdvertisingPeer];  
  925. }  
  926.   
  927. - (void)advertiseForProgrammaticDiscovery  
  928. {  
  929.     [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];  
  930. }  
  931.   
  932. - (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info  
  933. {  
  934.     //自定义自己,为了让其他设备搜索到自己  
  935.     self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];  
  936.     self.advertisingAssistant.delegate = self;  
  937.     [self.advertisingAssistant start];  
  938. }  
  939.   
  940. - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {  
  941.     self.invitationHandler = [invitationHandler copy];  
  942.     if(self.inviteBlock) self.inviteBlock(peerID, context);  
  943. }  
  944.   
  945. #pragma mark 下面是MCAdvertiserAssistant的两个代理  
  946. - (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant  
  947. {  
  948.     //TODO implement  
  949. }  
  950.   
  951. - (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {  
  952.     //TODO implement  
  953. }  
  954.   
  955. #pragma mark  扫描其他的设备  
  956. - (void)browseForProgrammaticDiscovery  
  957. {  
  958.       
  959.     self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];  
  960.     self.browser.delegate = self;  
  961.     [self.browser startBrowsingForPeers];  
  962.       
  963. }  
  964.   
  965. #pragma mark MCNearbyServiceBrowserDelegate   
  966. - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID  
  967. {  
  968.     //TODO implement  
  969. }  
  970.   
  971. - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info  
  972. {  
  973.     if(self.didFindPeer)  
  974.     {  
  975.         self.didFindPeer(peerID, info);  
  976.     }  
  977. }  
  978.   
  979. - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error  
  980. {  
  981.     //TODO implement  
  982. }  
  983.   
  984. #pragma mark 参加会议  也是会议的代理  
  985. //   也是  ----- MCSessionDelegate  
  986.   
  987. //  这是完成会议的结果···  
  988. - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error  
  989. {  
  990.       if(self.resourceFinalOnMainQueue)  
  991.     {  
  992.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  993.             if(self.finalResource)  
  994.             {  
  995.                 self.finalResource(resourceName, peerID, localURL, error);  
  996.             }  
  997.         }];  
  998.     }  
  999.     else  
  1000.     {  
  1001.         if(self.finalResource)  
  1002.         {  
  1003.             self.finalResource(resourceName, peerID, localURL, error);  
  1004.         }  
  1005.     }  
  1006. }  
  1007. // 这是参加  普通数据的会议  
  1008. - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID  
  1009. {  
  1010.     if(self.receiveOnMainQueue)  
  1011.     {  
  1012.     [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  1013.      if(self.receiveDataBlock){  
  1014.         self.receiveDataBlock(data, peerID);  
  1015.             }  
  1016.         }];  
  1017.     }  
  1018.     else  
  1019.     {  
  1020.         if(self.receiveDataBlock)  
  1021.         {  
  1022.             self.receiveDataBlock(data, peerID);  
  1023.         }  
  1024.     }  
  1025. }  
  1026. // 这是参加普通流的会议  
  1027. - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID  
  1028. {  
  1029.      if(self.streamBlock)  
  1030.     {  
  1031.         self.streamBlock(stream, peerID, streamName);  
  1032.     }  
  1033. }  
  1034. // 这是参加图片资源的会议  
  1035. - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress  
  1036. {  
  1037.     if(self.resourceStart)  
  1038.     {  
  1039.           
  1040.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  1041.             if(self.didStartReceivingResource)  
  1042.             {  
  1043.                 self.didStartReceivingResource(resourceName, peerID, progress);  
  1044.             }  
  1045.         }];  
  1046.     }  
  1047.     else  
  1048.     {  
  1049.         
  1050.         if(self.didStartReceivingResource)  
  1051.         {  
  1052.             self.didStartReceivingResource(resourceName, peerID, progress);  
  1053.         }  
  1054.     }  
  1055. }  
  1056.   
  1057.   
  1058. // 这是不同数据,系那是不同会议时候的状态  
  1059.   
  1060. - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state  
  1061. {  
  1062.     // 这个地方是当两个蓝牙设备一旦连接起来,就会形成的一个会议  
  1063.     if(self.statusOnMainQueue)  
  1064.     {  
  1065.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  1066.             if(self.connectionStatus)  
  1067.             {  
  1068.                 self.connectionStatus(peerID, state);  
  1069.             }  
  1070.         }];  
  1071.     }  
  1072.     else  
  1073.     {  
  1074.         if(self.connectionStatus)  
  1075.         {  
  1076.             self.connectionStatus(peerID, state);  
  1077.         }  
  1078.     }  
  1079. }  
  1080.   
  1081.   
  1082.   
  1083. #pragma mark  send And receive  
  1084. //--------------------------------------------------------------------------------------------//  
  1085. // 发送消息  
  1086. // 用户多个  
  1087. - (NSError *)sendDataToAllPeers:(NSData *)data  
  1088. {  
  1089.     // 普通数据的发送  
  1090.     return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];  
  1091. }  
  1092.   
  1093. - (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode  
  1094. {  
  1095.     // 确实进入会议  
  1096.     NSError *error;  
  1097.     [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];  
  1098.     return error;  
  1099. }  
  1100.   
  1101. // 用户确定一个  
  1102. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers  
  1103. {  
  1104.     return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];  
  1105. }  
  1106.   
  1107. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode  
  1108. {  
  1109.     NSError *error;  
  1110.     [self.session sendData:data toPeers:peers withMode:mode error:&error];  
  1111.     return error;  
  1112. }  
  1113.   
  1114.   
  1115. // 接收消息  
  1116. - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock  
  1117. {  
  1118.       
  1119.     self.receiveDataBlock = [dataBlock copy];  
  1120.     self.receiveOnMainQueue = mainQueue;  
  1121. }  
  1122. //--------------------------------------------------------------------------------------------//  
  1123.   
  1124. - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete  
  1125. {  
  1126.     // 图片资源数据的发送  
  1127.       
  1128.     return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];  
  1129. }  
  1130.   
  1131. // 用户连接确定   
  1132. - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status  
  1133. {  
  1134.     self.connectionStatus = [status copy];  
  1135.     self.statusOnMainQueue = mainQueue;  
  1136. }  
  1137.   
  1138.   
  1139. #pragma mark 自带的MCBrowserViewController类  
  1140. - (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController  
  1141. {  
  1142.     [browserViewController dismissViewControllerAnimated:YES completion:^{  
  1143.         if(self.browserConnected) self.browserConnected();  
  1144.     }];  
  1145. }  
  1146.   
  1147. - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController  
  1148. {  
  1149.     [browserViewController dismissViewControllerAnimated:YES completion:^{  
  1150.         if(self.browserCancelled) self.browserCancelled();  
  1151.     }];  
  1152. }  
  1153.   
  1154. - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled  
  1155. {  
  1156.     self.browserConnected = [connected copy];  
  1157.     self.browserCancelled = [cancelled copy];  
  1158.     // 注意这个自带的类  
  1159.     MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];  
  1160.     browser.delegate = self;  
  1161.     [controller presentViewController:browser animated:YES completion:nil];  
  1162. }  
  1163.   
  1164. - (NSArray *)connectedPeers  
  1165. {  
  1166.     return self.session.connectedPeers;  
  1167. }  
  1168.   
  1169. // 邀请某某连接  
  1170. - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;  
  1171. {  
  1172.     self.inviteBlock = [invite copy];  
  1173. }  
  1174.   
  1175. - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected  
  1176. {  
  1177.     [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];  
  1178. }  
  1179.   
  1180. - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block  
  1181. {  
  1182.       
  1183.     self.didStartReceivingResource = [block copy];  
  1184.     self.resourceStart = mainQueue;  
  1185. }  
  1186. // 接收某某资源  
  1187. - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block  
  1188. {  
  1189.     self.finalResource = [block copy];  
  1190.     self.resourceFinalOnMainQueue = mainQueue;  
  1191. }  
  1192. - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error  
  1193. {  
  1194.     return [self.session startStreamWithName:name toPeer:peerID error:error];  
  1195. }  
  1196. // 开始转化为流  
  1197. - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock  
  1198. {  
  1199.     self.streamBlock = [streamBlock copy];  
  1200. }  
  1201. - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found  
  1202. {  
  1203.     self.didFindPeer = [found copy];  
  1204. }  
  1205. #pragma mark  一些断开的情况  
  1206. - (void)disconnectSession  
  1207. {  
  1208.     [self.session disconnect];  
  1209. }  
  1210.   
  1211. - (void)stopAdvertising  
  1212. {  
  1213.     [self.advertiser stopAdvertisingPeer];  
  1214.     [self.advertisingAssistant stop];  
  1215. }  
  1216.   
  1217. - (void)stopBrowsing  
  1218. {  
  1219.     [self.browser stopBrowsingForPeers];  
  1220. }  
  1221.   
  1222. - (BOOL)isConnected {  
  1223.     return self.session.connectedPeers && self.session.connectedPeers.count > 0;  
  1224. }  
  1225.   
  1226. // 是否连接 它  
  1227. - (void)connectToPeer:(BOOL)connect {  
  1228.     self.invitationHandler(connect, self.session);  
  1229. }  
  1230.   
  1231. - (MCSession *)session {  
  1232.     return self.currentSession;  
  1233. }  
  1234.   
  1235. - (MCPeerID *)firstPeer {  
  1236.     return self.session.connectedPeers.firstObject;  
  1237. }  
  1238.   
  1239. @end  
  1240.   
  1241.   
  1242. .m  
  1243.   
  1244. #import "BlueSessionManager.h"  
  1245.   
  1246. #define ServiceType @"MyService"  
  1247.   
  1248. /* 
  1249.  MCAdvertiserAssistant   //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。 
  1250.  MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。 
  1251.  MCNearbyServiceBrowser  //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。 
  1252.  MCPeerID //这表明是一个用户 
  1253.  MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。 
  1254.  */  
  1255. @interface BlueSessionManager ()<MCAdvertiserAssistantDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate, MCNearbyServiceAdvertiserDelegate, UIAlertViewDelegate>  
  1256. @property(strong, nonatomic) MCSession *currentSession; // 当前会议  
  1257. @property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣传助手  
  1258. @property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服务助手  
  1259. @property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索蓝牙者  
  1260. @property(strong, nonatomic) MCPeerID *peerID; // 用户  
  1261.   
  1262. //  以下都是用到的block  
  1263. @property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);  
  1264. @property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);  
  1265. @property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);  
  1266. @property(nonatomic, copy) void(^browserConnected)(void);  
  1267. @property(nonatomic, copy) void(^browserCancelled)(void);  
  1268. @property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);  
  1269. @property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);  
  1270. @property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);  
  1271. @property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);  
  1272. @property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);  
  1273. @property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);  
  1274. // 各种判断  
  1275. @property(nonatomic, assign) BOOL receiveOnMainQueue;  
  1276. @property(nonatomic, assign) BOOL statusOnMainQueue;  
  1277. @property(nonatomic, assign) BOOL resourceFinalOnMainQueue;  
  1278. @property(nonatomic, assign) BOOL resourceStart;  
  1279. @end  
  1280. @implementation BlueSessionManager  
  1281. #pragma mark 初始化自己  
  1282. - (instancetype)initWithDisplayName:(NSString *)displayName  
  1283. {  
  1284.     return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];  
  1285. }  
  1286. // 为上面自定义 用户  
  1287. - (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type  
  1288. {  
  1289.     self = [super init];  
  1290.     if(!self) {  
  1291.         return nil;  
  1292.     }  
  1293.     self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];  
  1294.     self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];  
  1295.     self.session.delegate = self;  
  1296.     self.serviceType = type;  
  1297.     return self;  
  1298. }  
  1299. #pragma mark 宣传自己  
  1300. - (void)advertiseForBrowserViewController  
  1301. {  
  1302.     [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];  
  1303. }  
  1304.   
  1305. - (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info  
  1306. {  
  1307.     //  
  1308.     self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];  
  1309.     self.advertiser.delegate = self;  
  1310.     [self.advertiser startAdvertisingPeer];  
  1311. }  
  1312.   
  1313. - (void)advertiseForProgrammaticDiscovery  
  1314. {  
  1315.     [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];  
  1316. }  
  1317.   
  1318. - (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info  
  1319. {  
  1320.     //自定义自己,为了让其他设备搜索到自己  
  1321.     self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];  
  1322.     self.advertisingAssistant.delegate = self;  
  1323.     [self.advertisingAssistant start];  
  1324. }  
  1325.   
  1326. - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {  
  1327.     self.invitationHandler = [invitationHandler copy];  
  1328.     if(self.inviteBlock) self.inviteBlock(peerID, context);  
  1329. }  
  1330.   
  1331. #pragma mark 下面是MCAdvertiserAssistant的两个代理  
  1332. - (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant  
  1333. {  
  1334.     //TODO implement  
  1335. }  
  1336.   
  1337. - (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {  
  1338.     //TODO implement  
  1339. }  
  1340.   
  1341. #pragma mark  扫描其他的设备  
  1342. - (void)browseForProgrammaticDiscovery  
  1343. {  
  1344.       
  1345.     self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];  
  1346.     self.browser.delegate = self;  
  1347.     [self.browser startBrowsingForPeers];  
  1348.       
  1349. }  
  1350.   
  1351. #pragma mark MCNearbyServiceBrowserDelegate   
  1352. - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID  
  1353. {  
  1354.     //TODO implement  
  1355. }  
  1356.   
  1357. - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info  
  1358. {  
  1359.     if(self.didFindPeer)  
  1360.     {  
  1361.         self.didFindPeer(peerID, info);  
  1362.     }  
  1363. }  
  1364.   
  1365. - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error  
  1366. {  
  1367.     //TODO implement  
  1368. }  
  1369.   
  1370. #pragma mark 参加会议  也是会议的代理  
  1371. //   也是  ----- MCSessionDelegate  
  1372.   
  1373. //  这是完成会议的结果···  
  1374. - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error  
  1375. {  
  1376.       if(self.resourceFinalOnMainQueue)  
  1377.     {  
  1378.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  1379.             if(self.finalResource)  
  1380.             {  
  1381.                 self.finalResource(resourceName, peerID, localURL, error);  
  1382.             }  
  1383.         }];  
  1384.     }  
  1385.     else  
  1386.     {  
  1387.         if(self.finalResource)  
  1388.         {  
  1389.             self.finalResource(resourceName, peerID, localURL, error);  
  1390.         }  
  1391.     }  
  1392. }  
  1393. // 这是参加  普通数据的会议  
  1394. - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID  
  1395. {  
  1396.     if(self.receiveOnMainQueue)  
  1397.     {  
  1398.     [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  1399.      if(self.receiveDataBlock){  
  1400.         self.receiveDataBlock(data, peerID);  
  1401.             }  
  1402.         }];  
  1403.     }  
  1404.     else  
  1405.     {  
  1406.         if(self.receiveDataBlock)  
  1407.         {  
  1408.             self.receiveDataBlock(data, peerID);  
  1409.         }  
  1410.     }  
  1411. }  
  1412. // 这是参加普通流的会议  
  1413. - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID  
  1414. {  
  1415.      if(self.streamBlock)  
  1416.     {  
  1417.         self.streamBlock(stream, peerID, streamName);  
  1418.     }  
  1419. }  
  1420. // 这是参加图片资源的会议  
  1421. - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress  
  1422. {  
  1423.     if(self.resourceStart)  
  1424.     {  
  1425.           
  1426.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  1427.             if(self.didStartReceivingResource)  
  1428.             {  
  1429.                 self.didStartReceivingResource(resourceName, peerID, progress);  
  1430.             }  
  1431.         }];  
  1432.     }  
  1433.     else  
  1434.     {  
  1435.         
  1436.         if(self.didStartReceivingResource)  
  1437.         {  
  1438.             self.didStartReceivingResource(resourceName, peerID, progress);  
  1439.         }  
  1440.     }  
  1441. }  
  1442.   
  1443.   
  1444. // 这是不同数据,系那是不同会议时候的状态  
  1445.   
  1446. - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state  
  1447. {  
  1448.     // 这个地方是当两个蓝牙设备一旦连接起来,就会形成的一个会议  
  1449.     if(self.statusOnMainQueue)  
  1450.     {  
  1451.         [[NSOperationQueue mainQueue]addOperationWithBlock:^{  
  1452.             if(self.connectionStatus)  
  1453.             {  
  1454.                 self.connectionStatus(peerID, state);  
  1455.             }  
  1456.         }];  
  1457.     }  
  1458.     else  
  1459.     {  
  1460.         if(self.connectionStatus)  
  1461.         {  
  1462.             self.connectionStatus(peerID, state);  
  1463.         }  
  1464.     }  
  1465. }  
  1466.   
  1467.   
  1468.   
  1469. #pragma mark  send And receive  
  1470. //--------------------------------------------------------------------------------------------//  
  1471. // 发送消息  
  1472. // 用户多个  
  1473. - (NSError *)sendDataToAllPeers:(NSData *)data  
  1474. {  
  1475.     // 普通数据的发送  
  1476.     return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];  
  1477. }  
  1478.   
  1479. - (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode  
  1480. {  
  1481.     // 确实进入会议  
  1482.     NSError *error;  
  1483.     [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];  
  1484.     return error;  
  1485. }  
  1486.   
  1487. // 用户确定一个  
  1488. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers  
  1489. {  
  1490.     return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];  
  1491. }  
  1492.   
  1493. - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode  
  1494. {  
  1495.     NSError *error;  
  1496.     [self.session sendData:data toPeers:peers withMode:mode error:&error];  
  1497.     return error;  
  1498. }  
  1499.   
  1500.   
  1501. // 接收消息  
  1502. - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock  
  1503. {  
  1504.       
  1505.     self.receiveDataBlock = [dataBlock copy];  
  1506.     self.receiveOnMainQueue = mainQueue;  
  1507. }  
  1508. //--------------------------------------------------------------------------------------------//  
  1509.   
  1510. - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete  
  1511. {  
  1512.     // 图片资源数据的发送  
  1513.       
  1514.     return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];  
  1515. }  
  1516.   
  1517. // 用户连接确定   
  1518. - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status  
  1519. {  
  1520.     self.connectionStatus = [status copy];  
  1521.     self.statusOnMainQueue = mainQueue;  
  1522. }  
  1523.   
  1524.   
  1525. #pragma mark 自带的MCBrowserViewController类  
  1526. - (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController  
  1527. {  
  1528.     [browserViewController dismissViewControllerAnimated:YES completion:^{  
  1529.         if(self.browserConnected) self.browserConnected();  
  1530.     }];  
  1531. }  
  1532.   
  1533. - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController  
  1534. {  
  1535.     [browserViewController dismissViewControllerAnimated:YES completion:^{  
  1536.         if(self.browserCancelled) self.browserCancelled();  
  1537.     }];  
  1538. }  
  1539.   
  1540. - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled  
  1541. {  
  1542.     self.browserConnected = [connected copy];  
  1543.     self.browserCancelled = [cancelled copy];  
  1544.     // 注意这个自带的类  
  1545.     MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];  
  1546.     browser.delegate = self;  
  1547.     [controller presentViewController:browser animated:YES completion:nil];  
  1548. }  
  1549.   
  1550. - (NSArray *)connectedPeers  
  1551. {  
  1552.     return self.session.connectedPeers;  
  1553. }  
  1554.   
  1555. // 邀请某某连接  
  1556. - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;  
  1557. {  
  1558.     self.inviteBlock = [invite copy];  
  1559. }  
  1560.   
  1561. - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected  
  1562. {  
  1563.     [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];  
  1564. }  
  1565.   
  1566. - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block  
  1567. {  
  1568.       
  1569.     self.didStartReceivingResource = [block copy];  
  1570.     self.resourceStart = mainQueue;  
  1571. }  
  1572. // 接收某某资源  
  1573. - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block  
  1574. {  
  1575.     self.finalResource = [block copy];  
  1576.     self.resourceFinalOnMainQueue = mainQueue;  
  1577. }  
  1578. - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error  
  1579. {  
  1580.     return [self.session startStreamWithName:name toPeer:peerID error:error];  
  1581. }  
  1582. // 开始转化为流  
  1583. - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock  
  1584. {  
  1585.     self.streamBlock = [streamBlock copy];  
  1586. }  
  1587. - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found  
  1588. {  
  1589.     self.didFindPeer = [found copy];  
  1590. }  
  1591. #pragma mark  一些断开的情况  
  1592. - (void)disconnectSession  
  1593. {  
  1594.     [self.session disconnect];  
  1595. }  
  1596.   
  1597. - (void)stopAdvertising  
  1598. {  
  1599.     [self.advertiser stopAdvertisingPeer];  
  1600.     [self.advertisingAssistant stop];  
  1601. }  
  1602.   
  1603. - (void)stopBrowsing  
  1604. {  
  1605.     [self.browser stopBrowsingForPeers];  
  1606. }  
  1607.   
  1608. - (BOOL)isConnected {  
  1609.     return self.session.connectedPeers && self.session.connectedPeers.count > 0;  
  1610. }  
  1611.   
  1612. // 是否连接 它  
  1613. - (void)connectToPeer:(BOOL)connect {  
  1614.     self.invitationHandler(connect, self.session);  
  1615. }  
  1616.   
  1617. - (MCSession *)session {  
  1618.     return self.currentSession;  
  1619. }  
  1620.   
  1621. - (MCPeerID *)firstPeer {  
  1622.     return self.session.connectedPeers.firstObject;  
  1623. }  
  1624.   
  1625. @end  

最终效果只能真机测试,所以这里不做演示!
每日更新关注:http://weibo.com/hanjunqiang  新浪微博

原文地址:http://blog.csdn.net/qq_31810357/article/details/50204477

时间: 2024-09-13 21:28:39

iOS中 蓝牙2.0详解/ios蓝牙设备详解的相关文章

iOS中 蓝牙2.0详解/ios蓝牙设备详解 韩俊强的博客

每日更新关注:http://weibo.com/hanjunqiang  新浪微博 整体布局如下:     程序结构如右图: 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 ========================================================================== 指定根视图: RootViewController * rootVC = [[RootViewController alloc] init]

iOS中nil、Nil、NULL、NSNull详解

  这篇文章主要介绍了iOS中nil.Nil.NULL.NSNull详解的相关资料,需要的朋友可以参考下 ObjC 里面的几个空值符号经常会差点把我搞死,这些基础的东西一点要弄清楚才行,以提高码农的基本素质. nil nil 是 ObjC 对象的字面空值,对应 id 类型的对象,或者使用 @interface 声明的 ObjC 对象. 例如: ? 1 2 3 4 NSString *someString = nil; NSURL *someURL = nil; id someObject = n

iOS中关于信鸽推送的使用demo详解_IOS

最近在看推送方面的知识,用的是信鸽推送主要是因为后台用的是信鸽 推送用第三方推送,也就是在客户端建一个广播接收器,当服务器发送消息时发送到信鸽,信鸽再发送一次,广播接受器接受下: 我实现的功能比较简单,当app在运行状态时,会在主页展示一个弹窗展示推送的消息:如果app不在运行状态且service没被销毁就展示默认的通知 那么如何在主页展示弹窗:当广播接受器收到我要的消息时,用观察者模式,收到消息在发送个消息个主界面 官方的Demo连接:http://xg.qq.com/xg/help/ctr_

iOS中nil、Nil、NULL、NSNull详解_IOS

ObjC 里面的几个空值符号经常会差点把我搞死,这些基础的东西一点要弄清楚才行,以提高码农的基本素质. nil nil 是 ObjC 对象的字面空值,对应 id 类型的对象,或者使用 @interface 声明的 ObjC 对象. 例如: NSString *someString = nil; NSURL *someURL = nil; id someObject = nil; if (anotherObject == nil) // do something 定义: // objc.h #if

iOS中 语音识别功能/语音转文字教程详解 韩俊强的博客

原文地址:http://blog.csdn.net/qq_31810357/article/details/51111702 前言:最近研究了一下语音识别,从百度语音识别到讯飞语音识别:首先说一下个人针对两者的看法,讯飞毫无疑问比较专业,识别率也很高真对语音识别是比较精准的,但是很多开发者和我一样期望离线识别,而讯飞离线是收费的:请求次数来讲,两者都可以申请高配额,针对用户较多的几乎都一样.基于免费并且支持离线我选择了百度离线语音识别.比较简单,UI设计多一点,下面写一下教程: 1.首先:需要的

iOS中 语音识别功能/语音转文字教程详解

版权声明:本文为博主原创文章,未经博主允许不得转载. 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 原文地址:http://blog.csdn.net/qq_31810357/article/details/51111702 前言:最近研究了一下语音识别,从百度语音识别到讯飞语音识别:首先说一下个人针对两者的看法,讯飞毫无疑问比较专业,识别率也很高真对语音识别是比较精准的,但是很多开发者和我一样期望离线识别,而讯飞离线是收费的:请求次数来讲,两者都可以申请高

蓝牙4.0 For IOS

蓝牙4.0 For IOS 用于IOS,更多说的是开发有关 目录  [隐藏]  1 更多研究 2 发现 3 调试用APP 4 困扰 5 NRF8002 6 一些研究 6.1 官方Demo 7 CC2540官方源码 8 经验 9 IOS的蓝牙4.0支持 10 IOS库支持 11 官方文档说法 12 见识 12.1 [iOS][RCtank]在xcode的iOS虚拟机中对BLE(蓝牙4.0)进行调试_jianglurong_新浪博客 沿途见识[2] 12.2 在xcode的ios模拟器里调试BLE_

iOS简易蓝牙对战五子棋游戏设计思路之一——核心蓝牙通讯类的设计

iOS简易蓝牙对战五子棋游戏设计思路之一--核心蓝牙通讯类的设计 一.引言     本系列博客将系统的介绍一款蓝牙对战五子棋的开发思路与过程,其中的核心部分有两个,一部分是蓝牙通讯中对战双方信息交互框架的设计与开发,一部分是五子棋游戏中棋盘逻辑与胜负判定的算法实现.本篇博客将介绍游戏中蓝牙通讯类的设计思路 二.设计通讯类的核心想法    在前篇的一篇博客中,我们有详细的介绍iOS中蓝牙4.0技术的应用与系统框架CoorBluetooth.framework中提供的编程接口的用法.博客地址如下,如

IOS蓝牙4.0的使用问题

问题描述 IOS蓝牙4.0的使用问题 在IOS9.3和8.3平台上,使用系统的CoreBluetooth框架,创建蓝牙功能,发现根本扫描不到 任何设备,在AppStore上下载的蓝牙应用软件也有类似的问题.在网上搜出的博文都是大同小异,实现原理都差不多,出现的问题都是扫描不出设备!请问到底哪里出现问题了啊?真是烦死人了,下了n多个Demo,可都没有结果,求大神指教! 解决方案 iOS蓝牙4.0 BLE的使用IOS蓝牙4.0使用心得IOS蓝牙4.0简单使用