你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS中 藍牙2.0詳解/ios藍牙設備詳解 韓俊強的博客

iOS中 藍牙2.0詳解/ios藍牙設備詳解 韓俊強的博客

編輯:IOS開發綜合

 

整體布局如下:

\ 程序結構如右圖:\

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

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

指定根視圖:

 

    RootViewController * rootVC = [[RootViewController alloc] init];
    UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:rootVC];
    self.window.rootViewController= nav;
根視圖:

 

 

#import RootViewController.h
#import BlueSessionManager.h
#import ChatCell.h
#import ChatItem.h

#import 
#import 


#define kRecordAudioFile @myRecord.caf

// 判斷大小
#define HEIGHT [UIScreen mainScreen].bounds.size.height
#define WIDTH [UIScreen mainScreen].bounds.size.width
#define ChatHeight 45.0

@interface RootViewController ()
{
    float _sendBackViewHeight;
    float _sendTextViewHeight;
    
    UIImagePickerController * _picker;
    UIView * _backRemindRecordView;
}

// DataAndBlue
@property(strong, nonatomic) BlueSessionManager *sessionManager;

@property(strong, nonatomic) NSMutableArray *datasource;
@property(strong, nonatomic) NSMutableArray * myDataArray;

@property(strong, nonatomic) NSMutableData *streamData;
@property(strong, nonatomic) NSOutputStream *outputStream;
@property(strong, nonatomic) NSInputStream *inputStream;

// UI
@property(strong, nonatomic) UITableView * tableView;
@property(strong, nonatomic) UIView * sendBackView;
@property(strong, nonatomic) UITextView * sendTextView;
@property(strong, nonatomic) UIButton * sendButton;


// 語音播放
@property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音頻錄音機
//音頻播放器,用於播放錄音文件
@property (nonatomic,strong) AVAudioPlayer *audioPlayer;

@property (nonatomic,strong) NSTimer *timer;//錄音聲波監控(注意這裡暫時不對播放進行監控)



@property (strong, nonatomic) UIProgressView *audioPower;//音頻波動




@end

@implementation RootViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self makeBlueData];
    
    [self readyUI];
    
    [self buildVideoForWe];
    
    
    // Do any additional setup after loading the view
}




#pragma mark  基本制作

- (void)readyUI
{
    self.title = @藍牙設置;
    self.view.backgroundColor = [UIColor whiteColor];
    self.automaticallyAdjustsScrollViewInsets = NO;
    
    NSArray * buttonTitleArray = @[@尋找設備,@打開天線];
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:buttonTitleArray[0] style:UIBarButtonItemStyleDone target:self action:@selector(lookOtherDevice)];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:buttonTitleArray[1] style:UIBarButtonItemStyleDone target:self action:@selector(showSelfAdvertiser)];
    [self makeUIView];
    
}
- (void)lookOtherDevice
{
    [self.sessionManager browseWithControllerInViewController:self connected:^{
        NSLog(@connected);
    }                                                 canceled:^{
        NSLog(@cancelled);
    }];
}


- (void)showSelfAdvertiser
{
    [self.sessionManager advertiseForBrowserViewController];
}

#pragma mark 制作頁面UI
- (void)makeUIView
{
//    NSLog(@width === %f,height===== %f,WIDTH,HEIGHT);
    
    self.myDataArray = [NSMutableArray arrayWithCapacity:0];
    
    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10)];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.separatorStyle = UITableViewCellSelectionStyleNone;
   
    [self.view addSubview:self.tableView];
    
   
    
    
   
//-------------------------------------------------------------------------//
    
    self.sendBackView = [[UIView alloc] initWithFrame:CGRectMake(0, HEIGHT - ChatHeight, WIDTH, ChatHeight)];
    self.sendBackView.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];
    [self.view addSubview:self.sendBackView];
    
//    float heightView = self.sendBackView.frame.size.height;
    
    self.sendTextView = [[UITextView alloc] initWithFrame:CGRectMake(10, 5, WIDTH - 10 - 90, 35)];
//    self.sendTextView.backgroundColor = [UIColor lightGrayColor];
    self.sendTextView.returnKeyType = UIReturnKeySend;
    self.sendTextView.font = [UIFont systemFontOfSize:17];
    self.sendTextView.editable = YES;
    self.sendTextView.delegate = self;
    [self.sendBackView addSubview:self.sendTextView];
    
    UIButton * addButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
    addButton.frame = CGRectMake(WIDTH - 85, 2, 37, 37);
    [addButton addTarget:self action:@selector(addNextImage) forControlEvents:UIControlEventTouchUpInside];
    [self.sendBackView addSubview:addButton];
    
    self.sendButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.sendButton.frame = CGRectMake(WIDTH - 45, 5, 40, 30);
    
    [self.sendButton setImage:[UIImage imageNamed:@record.png] forState:UIControlStateNormal];
    [self.sendButton addTarget:self action:@selector(videoRecord) forControlEvents:UIControlEventTouchUpInside];
    [self.sendBackView addSubview:self.sendButton];
    
  
    
    
    // 增加通知
    [self addTheNoticeForKeyDownUp];
    
}


#pragma mark 圖片的傳輸---------///////

- (void)addNextImage
{
   
    UIActionSheet *chooseImageSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@取消 destructiveButtonTitle:nil otherButtonTitles:@照相機,@相冊, nil];
    [chooseImageSheet showInView:self.view];
}




#pragma mark UIActionSheetDelegate Method
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    _picker = [[UIImagePickerController alloc] init];
    _picker.delegate = self;
    
    switch (buttonIndex) {
        case 0://Take picture
            
     
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
            {
                
                _picker.sourceType = UIImagePickerControllerSourceTypeCamera;
            }
        
            [self presentViewController:_picker animated:NO completion:nil];
            
            
      
            break;
            
        case 1:
            //From album
            _picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            
            [self presentViewController:_picker animated:NO completion:^{
                
                // 改變狀態欄的顏色  為正常  這是這個獨有的地方需要處理的
                [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
            }];
            break;
            
        default:
            
            break;
    }
}







// 相冊
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    
    NSString *type = [info objectForKey:UIImagePickerControllerMediaType];
    //當選擇的類型是圖片
    if ([type isEqualToString:@public.image])
    {
        //先把圖片轉成NSData
        UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
        NSData *data;
        if (UIImagePNGRepresentation(image) == nil)
        {
            data = UIImageJPEGRepresentation(image, 1.0);
        }
        else
        {
            data = UIImagePNGRepresentation(image);
        }
        
        //圖片保存的路徑
        //這裡將圖片放在沙盒的documents文件夾中
        NSString * DocumentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@Documents];
        
        //文件管理器
        NSFileManager *fileManager = [NSFileManager defaultManager];
        
        //把剛剛圖片轉換的data對象拷貝至沙盒中 並保存為image.png
        [fileManager createDirectoryAtPath:DocumentsPath withIntermediateDirectories:YES attributes:nil error:nil];
        [fileManager createFileAtPath:[DocumentsPath stringByAppendingString:@/image.png] contents:data attributes:nil];
        
        //得到選擇後沙盒中圖片的完整路徑
        NSString * filePath = [[NSString alloc]initWithFormat:@%@%@,DocumentsPath,  @/image.png];
        
        
        
        [_picker dismissViewControllerAnimated:NO completion:^{
            
            // 改變狀態欄的顏色  改變為白色
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
            
            
            
            // 這邊是真正的發送
            if(!self.sessionManager.isConnected)
            {
                UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@藍牙已經斷開了,請重新連接! message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@知道了, nil];
                [alertView show];
                return;
            }
            
            ChatItem * chatItem = [[ChatItem alloc] init];
            chatItem.isSelf = YES;
            chatItem.states = picStates;
            chatItem.picImage = image;
            [self.datasource addObject:chatItem];
            
            
            [self insertTheTableToButtom];
            
            
            [self sendAsResource:filePath];
           
        }];
    }

  
}
- (void)sendAsResource:(NSString *)path
{
    
    NSLog(@dispaly ====%@,self.sessionManager.firstPeer.displayName);
    NSString * name = [NSString stringWithFormat:@%@ForPic,[[UIDevice currentDevice] name]];
    NSURL * url = [NSURL fileURLWithPath:path];
    
    NSProgress *progress = [self.sessionManager sendResourceWithName:name atURL:url toPeer:self.sessionManager.firstPeer complete:^(NSError *error) {
        if(!error) {
            NSLog(@finished sending resource);
        }
        else {
            NSLog(@%@, error);
        }
    }];
    NSLog(@%@, @(progress.fractionCompleted));
}


#pragma mark 普通數據的傳輸
- (void)sendWeNeedNews
{
    if(!self.sessionManager.isConnected)
    {
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@藍牙已經斷開了,請重新連接! message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@知道了, nil];
        [alertView show];
        return;
    }
    if([self.sendTextView.text isEqualToString:@])
    {
        return;
    }
    
    
    ChatItem * chatItem = [[ChatItem alloc] init];
    chatItem.isSelf = YES;
    chatItem.states = textStates;
    chatItem.content = self.sendTextView.text;
    [self.datasource addObject:chatItem];
    // 加到數組裡面
    
    // 添加行   indexPath描述位置的具體信息
    [self insertTheTableToButtom];
    
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.sendTextView.text];
    NSError *error = [self.sessionManager sendDataToAllPeers:data];
    if(!error) {
        //there was no error.
    }
    else {
        NSLog(@%@, error);
    }
    
    [self returnTheNewBack];
}
- (void)returnTheNewBack
{
    // 歸零
    self.sendTextView.text = @;
    [self.sendTextView resignFirstResponder];
    self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10 );
    self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight , WIDTH, ChatHeight);
    
}

// 這是一種很好的鍵盤下移方式
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    
    if ([text isEqualToString:@
]) {
        
        [self sendWeNeedNews];

        return NO;
    }
    
    
    
    
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView
{

    // 隨機改變其高度
    
    float textHeight = [self heightForString:textView.text fontSize:16 andWidth:textView.frame.size.width];
    _sendTextViewHeight = textHeight;
//    NSLog(@teztheight ===== %f,textHeight);
    
    
    self.sendTextView.frame = CGRectMake(10, 5, WIDTH - 10 - 90, _sendTextViewHeight);
    self.sendBackView.frame = CGRectMake(0, HEIGHT -  _sendBackViewHeight - _sendTextViewHeight - 10, WIDTH, _sendTextViewHeight + 10);
  
    
}

- (float) heightForString:(NSString *)value fontSize:(float)fontSize andWidth:(float)width
{
    UITextView *detailTextView = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, width, 0)];
    detailTextView.font = [UIFont systemFontOfSize:fontSize];
    detailTextView.text = value;
    CGSize deSize = [detailTextView sizeThatFits:CGSizeMake(width,CGFLOAT_MAX)];
    return deSize.height;
}



#pragma mark 以下是為了配合  鍵盤上移的變化

- (void)addTheNoticeForKeyDownUp
{
    [ [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyBoardDidShow:) name:UIKeyboardDidShowNotification object:nil];
    [ [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

-(void)handleKeyBoardDidShow:(NSNotification *)paramNotification
{
    CGSize size = [[paramNotification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    
    _sendBackViewHeight = size.height;
    
    [UIView animateWithDuration:0.000001 animations:^{
        self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - size.height);
        self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight - size.height, WIDTH, ChatHeight);
        
    }];
    
}
-(void)handleKeyboardWillHide:(NSNotification *)paramNotification
{
    [UIView animateWithDuration:0.1 animations:^{
        if(_sendTextViewHeight > 0)
        {
            self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - _sendTextViewHeight + 10 );
            self.sendBackView.frame = CGRectMake(0, HEIGHT - _sendTextViewHeight  - 10, WIDTH, _sendTextViewHeight + 10);
        }
        else
        {
            self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10 );
            self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight , WIDTH, ChatHeight);
        }
        
        
    }];
}
/*--------------------------------------------------------------------------------------------*/
- (void)insertTheTableToButtom
{
    // 哪一組 哪一段
    NSIndexPath * indexPath = [NSIndexPath indexPathForRow:self.datasource.count- 1 inSection:0];
    // 添加新的一行
    [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    // 滑動到底部  第二個參數是滑動到底部
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

#pragma mark tableView 代理
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.datasource.count;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ChatItem * chatItem = [self.datasource objectAtIndex:indexPath.row];
    if(chatItem.states == picStates)
    {
        NSLog(@widht====%f,height======%f,chatItem.picImage.size.width,chatItem.picImage.size.height);
        return 50;
        
        
        
    }
    else if(chatItem.states == textStates)
    {
        CGSize size = [chatItem.content boundingRectWithSize:CGSizeMake(250, 1000) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading  attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:14]} context:nil].size;
        
        return size.height + 20 + 10; // 與view的距離 + 與Cell的距離
    }
    else
    {
        return 50;
    }
    
    
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    static NSString * iden = @iden;
    ChatCell * cell = [tableView dequeueReusableCellWithIdentifier:iden];
    if(cell == nil)
    {
        cell = [[ChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:iden];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        // 讓後面選中的沒有陰影效果
        
    }
    
    // 模型
    
    ChatItem * chatItem = [self.datasource objectAtIndex:indexPath.row];
   
    CGSize size = [chatItem.content boundingRectWithSize:CGSizeMake(250, 1000) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading  attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:14]} context:nil].size;
    
    //如果自己發的
    if(chatItem.isSelf)
    {
        cell.leftHeadImage.hidden = YES;
        cell.rightHeadImage.hidden = NO;
        
        if(chatItem.states == picStates)
        {
            cell.lefeView.hidden = YES;
            cell.rightView.hidden = YES;
            
            cell.rightPicImage.image = chatItem.picImage;
            cell.leftPicImage.hidden = YES;
            cell.rightPicImage.hidden = NO;
            
            cell.leftVideoButton.hidden = YES;
            cell.rightVideoButton.hidden = YES;
            
            NSLog(@self send);
           
            
        }
        else if(chatItem.states == textStates)
        {
            cell.rightPicImage.hidden = YES;
            cell.leftPicImage.hidden = YES;
            
            cell.lefeView.hidden = YES;
            cell.rightView.hidden = NO;
            
            cell.leftVideoButton.hidden = YES;
            cell.rightVideoButton.hidden = YES;
            // 復用機制
            cell.rightLabel.frame = CGRectMake(10, 5, size.width, size.height);
            cell.rightView.frame = CGRectMake(WIDTH - 40 -size.width-25, 5, size.width + 25, size.height + 18);
            cell.rightLabel.text = chatItem.content;
        }
        else
        {
            cell.rightView.hidden = YES;
            cell.lefeView.hidden = YES;
            cell.rightView.hidden = YES;
            cell.lefeView.hidden = YES;
            
            cell.leftVideoButton.hidden = YES;
            cell.rightVideoButton.hidden = NO;
            
            cell.rightVideoButton.tag = 300 + indexPath.row;
            [cell.rightVideoButton addTarget:self action:@selector(cellSelectIndex:) forControlEvents:UIControlEventTouchUpInside];
            [cell.rightVideoButton setImage:[UIImage imageNamed:@record.png] forState:UIControlStateNormal];
            
        }
        
        
        
        
        
        
        
    }
    else  // 接受得到
    {
        cell.leftHeadImage.hidden = NO;
        cell.rightHeadImage.hidden = YES;
       
        
        
        if(chatItem.states == picStates)
        {
            cell.rightView.hidden = YES;
            cell.lefeView.hidden = YES;
            
            cell.leftVideoButton.hidden = YES;
            cell.rightVideoButton.hidden = YES;
            
            cell.leftPicImage.image = chatItem.picImage;
            cell.rightPicImage.hidden = YES;
            cell.leftPicImage.hidden = NO;
            
           
            
            
        }
        else if(chatItem.states == textStates)
        {
            cell.rightPicImage.hidden = YES;
            cell.leftPicImage.hidden = YES;
            
            cell.rightView.hidden = YES;
            cell.lefeView.hidden = NO;
            
            cell.leftVideoButton.hidden = YES;
            cell.rightVideoButton.hidden = YES;
            
            cell.leftLabel.frame = CGRectMake(15, 5, size.width, size.height);
            
            cell.lefeView.frame = CGRectMake(40, 5, size.width +30, size.height + 25);
            
            cell.leftLabel.text = chatItem.content;
        }
        else
        {
            cell.rightView.hidden = YES;
            cell.lefeView.hidden = YES;
            cell.rightView.hidden = YES;
            cell.lefeView.hidden = YES;
            
            cell.leftVideoButton.hidden = NO;
            cell.rightVideoButton.hidden = YES;
            
            
            cell.leftVideoButton.tag = 300 + indexPath.row;
            [cell.leftVideoButton setImage:[UIImage imageNamed:@record.png] forState:UIControlStateNormal];
            [cell.leftVideoButton addTarget:self action:@selector(cellSelectIndex:) forControlEvents:UIControlEventTouchUpInside];
        }
        
        
        
    }

    
    return cell;
}

- (void)cellSelectIndex:(UIButton *)cellBtn
{
    
    ChatItem *chatIden = [self.datasource objectAtIndex:cellBtn.tag - 300];
    if(chatIden.states == videoStates)
    {
        NSLog(@realy play);
//        [self makeVideoPlayer:[self getVideoStremData]];
        [self makeVideoPlayer:chatIden.recordData];
    }
}


#pragma mark 下面是核心的連接MCSession 和  數據返回的地方

/***************************-------**********************************************/
- (void)makeBlueData
{
      // 這是為了讓 在block中弱引用
    __weak typeof (self) weakSelf = self;
    self.datasource = [NSMutableArray arrayWithCapacity:0];
    
    // 初始化  會議室
    self.sessionManager = [[BlueSessionManager alloc]initWithDisplayName:[NSString stringWithFormat:@ %@,  [[UIDevice currentDevice] name]]];
    
    //
    [self.sessionManager didReceiveInvitationFromPeer:^void(MCPeerID *peer, NSData *context) {
        __strong typeof (weakSelf) strongSelf = weakSelf;
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@是否連接? message:[NSString stringWithFormat:@同 %@%@, peer.displayName, @ 連接?] delegate:strongSelf cancelButtonTitle:@取消 otherButtonTitles:@確定, nil];
        [alertView show];
    }];
    
    [self.sessionManager peerConnectionStatusOnMainQueue:YES block:^(MCPeerID *peer, MCSessionState state) {
        if(state == MCSessionStateConnected) {
            UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@已經連接 message:[NSString stringWithFormat:@現在連接 %@了!, peer.displayName] delegate:nil cancelButtonTitle:nil otherButtonTitles:@知道了, nil];
            [alertView show];
        }
    }];
    
    // 發正常數據的返回
    [self.sessionManager receiveDataOnMainQueue:YES block:^(NSData *data, MCPeerID *peer) {
       
        __strong typeof (weakSelf) strongSelf = weakSelf;
        
        NSString *string = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        
        
        ChatItem * chatItem = [[ChatItem alloc] init];
        chatItem.isSelf = NO;
        chatItem.states = textStates;
        chatItem.content = string;
        [strongSelf.datasource addObject:chatItem];
        // 加到數組裡面
        
        [strongSelf insertTheTableToButtom];
        
        
    }];
    
    // 發圖片之後的返回
    [self.sessionManager receiveFinalResourceOnMainQueue:YES complete:^(NSString *name, MCPeerID *peer, NSURL *url, NSError *error) {
        
        __strong typeof (weakSelf) strongSelf = weakSelf;
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        ChatItem * chatItem = [[ChatItem alloc] init];
        chatItem.isSelf = NO;
        chatItem.states = picStates;
        chatItem.content = name;
        chatItem.picImage = [UIImage imageWithData:data];
        [strongSelf.datasource addObject:chatItem];
        [strongSelf insertTheTableToButtom];
        
    }];
    
    
    
    // 流
    [self.sessionManager didReceiveStreamFromPeer:^(NSInputStream *stream, MCPeerID *peer, NSString *streamName) {
        __strong typeof (weakSelf) strongSelf = weakSelf;
        strongSelf.inputStream = stream;
        strongSelf.inputStream.delegate = self;
        [strongSelf.inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        [strongSelf.inputStream open];
        
        NSLog(@we need);
        
    }];
    
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    [self.sessionManager connectToPeer:buttonIndex == 1];
}





#pragma mark 下面是流的傳輸

/***********--------------------- 下面是流的傳輸 ------------------------***********************************/

- (void)videoRecord
{
    // 播放錄音
    [self SetTempRecordView];
}


- (void)sendAsStream
{
    if(!self.sessionManager.isConnected)
    {
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@藍牙已經斷開了,請重新連接! message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@知道了, nil];
        [alertView show];
        return;
    }
   
    NSError *err;
    self.outputStream = [self.sessionManager streamWithName:@super stream toPeer:self.sessionManager.firstPeer error:&err];
    self.outputStream.delegate = self;
    [self.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    if(err || !self.outputStream) {
        NSLog(@%@, err);
    }
    else
    {
        
        [self.outputStream open];
    }
}

// 下面是一個代理
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
   
    if(eventCode == NSStreamEventHasBytesAvailable)
    {
         // 有可讀的字節,接收到了數據
        NSInputStream *input = (NSInputStream *)aStream;
        uint8_t buffer[1024];
        NSInteger length = [input read:buffer maxLength:1024];
        [self.streamData appendBytes:(const void *)buffer length:(NSUInteger)length];
       // 記住這邊的數據陸陸續續的
    }
    else if(eventCode == NSStreamEventHasSpaceAvailable)
    {
        // 可以使用輸出流的空間,此時可以發送數據給服務器
        // 發送數據的
        NSData *data = [self getVideoStremData];
        ChatItem * chatItem = [[ChatItem alloc] init];
        chatItem.isSelf = YES;
        chatItem.states = videoStates;
        chatItem.recordData = data;
        
        [self.datasource addObject:chatItem];
        [self insertTheTableToButtom];
        
        NSOutputStream *output = (NSOutputStream *)aStream;
        [output write:data.bytes maxLength:data.length];
        [output close];
    }
    if(eventCode == NSStreamEventEndEncountered)
    {
        // 流結束事件,在此事件中負責做銷毀工作
        // 同時也是獲得最終數據的好地方
        
        ChatItem * chatItem = [[ChatItem alloc] init];
        chatItem.isSelf = NO;
        chatItem.states = videoStates;
        chatItem.recordData = self.streamData;
        
        [self.datasource addObject:chatItem];
        [self insertTheTableToButtom];
        
        [aStream close];
        [aStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        if([aStream isKindOfClass:[NSInputStream class]])
        {
            self.streamData = nil;
        }
        
    }
    if(eventCode == NSStreamEventErrorOccurred)
    {
        // 發生錯誤
        NSLog(@error);
    }
}

- (NSMutableData *)streamData
{
    if(!_streamData) {
        _streamData = [NSMutableData data];
    }
    return _streamData;
}

/***********-----------------------  公用的數據 --------------------***********************************/

- (NSData *)imageData
{
    return [NSData dataWithContentsOfURL:[self imageURL]];
}

- (NSURL *)imageURL {
    NSString *path = [[NSBundle mainBundle]pathForResource:@301-alien-ship@2x ofType:@png];
    // 這兒有個技術點
    // 那個如何將 image轉化成 路徑
   
    NSURL *url = [NSURL fileURLWithPath:path];
    return url;
}

/***********----------------------------------------------***********************************/
#pragma mark 嘗試空白處的連接

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch * touch = [[event allTouches] anyObject];
    if(touch.tapCount >= 1)
    {
        [self.sendTextView resignFirstResponder];
    }
}


/***********-------------------語音---------------------------***********************************/

#pragma mark 嘗試語音的錄制和播出

- (void)buildVideoForWe
{
    // 設置錄音會話
    [self setAudioSession];
}

- (void)SetTempRecordView
{
    _backRemindRecordView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, 150)];
    _backRemindRecordView.center = self.view.center;
    _backRemindRecordView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:_backRemindRecordView];
    
    
    UILabel * beginLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 50, WIDTH -120, 50)];
    beginLabel.backgroundColor = [UIColor greenColor];
    beginLabel.text = @長按錄音開始···;
    beginLabel.tag = 1001;
    beginLabel.textAlignment = NSTextAlignmentCenter;
    beginLabel.userInteractionEnabled = YES;
    [_backRemindRecordView addSubview:beginLabel];
    
    UILongPressGestureRecognizer * longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressNextDo:)];
    [beginLabel addGestureRecognizer:longPress];
    

    
    
    
    
}



- (void)longPressNextDo:(UILongPressGestureRecognizer * )longPress
{
    if(longPress.state == UIGestureRecognizerStateBegan)
    {
        NSLog(@begin);
        UILabel * label = (UILabel *)[_backRemindRecordView viewWithTag:1001];
        label.text = @錄音正在進行中···;
        label.backgroundColor = [UIColor orangeColor];
        [self BeginRecordClick];
    }
    if(longPress.state == UIGestureRecognizerStateEnded)
    {
        [self OkStopClick];
        [_backRemindRecordView removeFromSuperview];
        [self  sendAsStream];
        NSLog(@stop);
       
    }
}


#pragma mark - 私有方法
/**
 *  設置音頻會話
 */
-(void)setAudioSession
{
    AVAudioSession *audioSession=[AVAudioSession sharedInstance];
    //設置為播放和錄音狀態,以便可以在錄制完之後播放錄音
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [audioSession setActive:YES error:nil];
}

/**
 *  取得錄音文件保存路徑
 *
 *  @return 錄音文件路徑
 */
-(NSURL *)getSavePath
{
    NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    urlStr=[urlStr stringByAppendingPathComponent:kRecordAudioFile];
    NSLog(@file path:%@,urlStr);
    NSURL *url=[NSURL fileURLWithPath:urlStr];
    return url;
}

- (NSData *)getVideoStremData
{
    return [NSData dataWithContentsOfURL:[self getSavePath]];
}


/**
 *  取得錄音文件設置
 *
 *  @return 錄音設置
 */
-(NSDictionary *)getAudioSetting{
    NSMutableDictionary *dicM=[NSMutableDictionary dictionary];
    //設置錄音格式
    [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
    //設置錄音采樣率,8000是電話采樣率,對於一般錄音已經夠了
    [dicM setObject:@(8000) forKey:AVSampleRateKey];
    //設置通道,這裡采用單聲道
    [dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
    //每個采樣點位數,分為8、16、24、32
    [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
    //是否使用浮點數采樣
    [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
    //....其他設置等
    return dicM;
}

/**
 *  獲得錄音機對象
 *
 *  @return 錄音機對象
 */
-(AVAudioRecorder *)audioRecorder
{
    if (!_audioRecorder) {
        //創建錄音文件保存路徑
        NSURL *url=[self getSavePath];
        //創建錄音格式設置
        NSDictionary *setting=[self getAudioSetting];
        //創建錄音機
        NSError *error=nil;
        _audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
        _audioRecorder.delegate=self;
        _audioRecorder.meteringEnabled=YES;//如果要監控聲波則必須設置為YES
        if (error) {
            NSLog(@創建錄音機對象時發生錯誤,錯誤信息:%@,error.localizedDescription);
            return nil;
        }
    }
    return _audioRecorder;
}

/**
 *  創建播放器
 *
 *  @return 播放器
 */


- (void)makeVideoPlayer:(NSData *)data
{
    NSError *error=nil;
    self.audioPlayer=[[AVAudioPlayer alloc]initWithData:data error:&error];
    self.audioPlayer.delegate = self;
    self.audioPlayer.numberOfLoops=0;
    [self.audioPlayer prepareToPlay];
    if (error)
    {
        NSLog(@創建播放器過程中發生錯誤,錯誤信息:%@,error.localizedDescription);
       
    }
    else
    {
        if (![self.audioPlayer isPlaying]) {
            NSLog(@play);
                [self.audioPlayer play];
        }
        
    }
}





/**
 *  錄音聲波監控定制器
 *
 *  @return 定時器
 */
-(NSTimer *)timer{
    if (!_timer) {
        _timer=[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(audioPowerChange) userInfo:nil repeats:YES];
    }
    return _timer;
}

/**
 *  錄音聲波狀態設置
 */
-(void)audioPowerChange{
    [self.audioRecorder updateMeters];//更新測量值
    float power= [self.audioRecorder averagePowerForChannel:0];//取得第一個通道的音頻,注意音頻強度范圍時-160到0
    CGFloat progress=(1.0/160.0)*(power+160.0);
    [self.audioPower setProgress:progress];
}
#pragma mark - UI事件
/**
 *  點擊錄音按鈕
 *
 *  @param sender 錄音按鈕
 */
- (void)BeginRecordClick
{
    if (![self.audioRecorder isRecording])
    {
        [self.audioRecorder record];//首次使用應用時如果調用record方法會詢問用戶是否允許使用麥克風
        self.timer.fireDate=[NSDate distantPast];
    }
}

/**
 *  點擊暫定按鈕
 *
 *  @param sender 暫停按鈕
 */
- (void)StopPauseClick
{
    if ([self.audioRecorder isRecording]) {
        [self.audioRecorder pause];
        self.timer.fireDate=[NSDate distantFuture];
    }
}


/**
 *  點擊停止按鈕
 *
 *  @param sender 停止按鈕
 */
- (void)OkStopClick
{
    [self.audioRecorder stop];
    self.timer.fireDate=[NSDate distantFuture];
    self.audioPower.progress=0.0;
}

#pragma mark - 錄音機代理方法
/**
 *  錄音完成,錄音完成後播放錄音
 *
 *  @param recorder 錄音機對象
 *  @param flag     是否成功
 */
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
//    if (![self.audioPlayer isPlaying]) {
//        [self.audioPlayer play];
//    }
    NSLog(@錄音完成!);
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    
    // 每次完成後都將這個對象釋放
    player =nil;
}

建一個model類:
.h
#import 
//@protocol CellSelectIndex 
//
//- (void)cellSelectIndex;
//
//@end


@interface ChatCell : UITableViewCell
@property(nonatomic,strong)UIImageView * lefeView;
@property(nonatomic,strong)UIImageView * rightView;
@property(nonatomic,strong)UILabel * leftLabel;
@property(nonatomic,strong)UILabel * rightLabel;

@property(nonatomic,strong)UIImageView * leftHeadImage;
@property(nonatomic,strong)UIImageView * rightHeadImage;

@property(nonatomic,strong)UIImageView * leftPicImage;
@property(nonatomic,strong)UIImageView * rightPicImage;


@property(nonatomic ,strong)UIButton * leftVideoButton;
@property(nonatomic, strong)UIButton * rightVideoButton;

//@property(nonatomic,weak)id  delegate;

// 不能用名字相同的屬性
//  記住自動的時候,講一下 weak  and strong 

@end


.m
#import ChatCell.h

@implementation ChatCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
        [self makeView];
    }
    return self;
}
-(void)makeView
{
    UIImage * leftImgae = [UIImage imageNamed:@ReceiverTextNodeBkg.png];
    UIImage * rightImage = [UIImage imageNamed:@SenderTextNodeBkg.png];
    
    //這裡設定一行一像素 當圖片拉伸的時候,只放大兩個像素
    
    leftImgae = [leftImgae stretchableImageWithLeftCapWidth:30 topCapHeight:35];
    // 找一行一列的像素
    rightImage = [rightImage stretchableImageWithLeftCapWidth:30 topCapHeight:35];
    // 設定完了後生成了一個新的image;
    
//----------------------------------------------------------------------------------------//
    // 左邊頭像
    self.leftHeadImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 30, 30)];
    self.leftHeadImage.layer.masksToBounds = YES;
    self.leftHeadImage.layer.cornerRadius = 12;
    self.leftHeadImage.image = [UIImage imageNamed:@f-pCert.png];
    [self.contentView addSubview:self.leftHeadImage];
    
    //左邊氣泡
    self.leftVideoButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.leftVideoButton.frame = CGRectMake(40, 5, 35, 35);
//    [self.leftVideoButton addTarget:self action:@selector(recordTheVoice) forControlEvents:UIControlEventTouchUpInside];
    [self.contentView addSubview:self.leftVideoButton];
    
    self.leftPicImage = [[UIImageView alloc] initWithFrame:CGRectMake(40, 5, 66, 30)];
    [self.contentView addSubview:self.leftPicImage];
    
    self.lefeView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 5, 66, 30)];
    self.lefeView.image = leftImgae;
    // 這裡不是一個小像素的圖片??
    [self.contentView addSubview:self.lefeView];
    
    
    self.leftLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 5, 1, 1)];
    self.leftLabel.font = [UIFont systemFontOfSize:14];
    
    self.leftLabel.numberOfLines = 0; // 換行
    
    self.leftLabel.backgroundColor = [UIColor clearColor];// 設置透明的
    
    [self.lefeView addSubview:self.leftLabel];
    
//----------------------------------------------------------------------------------------//
    
    self.rightHeadImage = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - 35, 5, 30, 30)];
    self.rightHeadImage.layer.masksToBounds = YES;
    self.rightHeadImage.layer.cornerRadius = 12;
    self.rightHeadImage.image = [UIImage imageNamed:@f-plove.png];
    [self.contentView addSubview:self.rightHeadImage];
    
    self.rightVideoButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.rightVideoButton.frame = CGRectMake(self.frame.size.width - 45 - 40, 5, 35, 35);
//    [self.rightVideoButton addTarget:self action:@selector(recordTheVoice) forControlEvents:UIControlEventTouchUpInside];
    [self.contentView addSubview:self.rightVideoButton];
    
    self.rightPicImage = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - 45 - 30, 5, 30, 30)];
    [self.contentView addSubview:self.rightPicImage];
    
    // 右邊
    self.rightView = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - (66+40), 5, 66, 30)];
    self.rightView.image = rightImage;
    [self.contentView addSubview:self.rightView];

    
    self.rightLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 1, 1)];
    self.rightLabel.font = [UIFont systemFontOfSize:14];
    self.rightLabel.backgroundColor = [UIColor clearColor];
    self.rightLabel.numberOfLines = 0;
    [self.rightView addSubview:self.rightLabel];
 
}

//- (void)recordTheVoice
//{
//    [self.delegate cellSelectIndex];
//}
每日更新關注:http://weibo.com/hanjunqiang 新浪微博

 

基本知識必須了解的

MCAdvertiserAssistant //可以接收,並處理用戶請求連接的響應。沒有回調,會彈出默認的提示框,並處理連接。

MCNearbyServiceAdvertiser //可以接收,並處理用戶請求連接的響應。但是,這個類會有回調,告知有用戶要與您的設備連接,然後可以自定義提示框,以及自定義連接處理。

MCNearbyServiceBrowser //用於搜索附近的用戶,並可以對搜索到的用戶發出邀請加入某個會話中。

MCPeerID //這表明是一個用戶

MCSession //啟用和管理Multipeer連接會話中的所有人之間的溝通。 通過Sesion,給別人發送數據。


建一個類用來寫所有方法:

 

.h
#import 

@import MultipeerConnectivity;

@interface BlueSessionManager : NSObject

@property(strong, nonatomic, readonly) NSArray *connectedPeers;

@property(strong, nonatomic, readonly) MCSession *session;

@property(nonatomic, readonly, getter = isConnected) BOOL connected;

@property(strong, nonatomic) NSDictionary *discoveryInfo; // 發現設備的特征

@property(strong, nonatomic, readonly) MCPeerID *firstPeer; // 第一個連接的 用戶

/**
 * The service type provided for browsing and advertising.
 * This should be a short text string that describes the
 * app's networking protocol. Should be something
 * in the form of `tjl_appname`.
 */
@property(strong, nonatomic) NSString *serviceType;


/*
 初始化一個 假設的用戶名字
 */
- (instancetype)__attribute__((nonnull(1)))initWithDisplayName:(NSString *)displayName;


- (void)browseForProgrammaticDiscovery;


- (void)advertiseForBrowserViewController;


- (void)advertiseForProgrammaticDiscovery;

- (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;


- (NSError *)sendDataToAllPeers:(NSData *)data;
- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers;


- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode;


- (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock;


- (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete;


- (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block;


- (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block;


- (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error;


- (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock;

- (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status;


- (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled;


- (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found;
- (void)connectToPeer:(BOOL)connect;

// 邀請其他設備連接
- (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected;
- (void)disconnectSession;
// 停止打開自己
- (void)stopAdvertising;

// 停止掃描
- (void)stopBrowsing;

@end




.m
#import BlueSessionManager.h

#define ServiceType @MyService

/*
 MCAdvertiserAssistant   //可以接收,並處理用戶請求連接的響應。沒有回調,會彈出默認的提示框,並處理連接。
 MCNearbyServiceAdvertiser //可以接收,並處理用戶請求連接的響應。但是,這個類會有回調,告知有用戶要與您的設備連接,然後可以自定義提示框,以及自定義連接處理。
 MCNearbyServiceBrowser  //用於搜索附近的用戶,並可以對搜索到的用戶發出邀請加入某個會話中。
 MCPeerID //這表明是一個用戶
 MCSession //啟用和管理Multipeer連接會話中的所有人之間的溝通。 通過Sesion,給別人發送數據。
 */
@interface BlueSessionManager ()
@property(strong, nonatomic) MCSession *currentSession; // 當前會議
@property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣傳助手
@property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服務助手
@property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索藍牙者
@property(strong, nonatomic) MCPeerID *peerID; // 用戶

//  以下都是用到的block
@property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);
@property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);
@property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);
@property(nonatomic, copy) void(^browserConnected)(void);
@property(nonatomic, copy) void(^browserCancelled)(void);
@property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);
@property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);
@property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);
@property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);
@property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);
@property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);
// 各種判斷
@property(nonatomic, assign) BOOL receiveOnMainQueue;
@property(nonatomic, assign) BOOL statusOnMainQueue;
@property(nonatomic, assign) BOOL resourceFinalOnMainQueue;
@property(nonatomic, assign) BOOL resourceStart;
@end
@implementation BlueSessionManager
#pragma mark 初始化自己
- (instancetype)initWithDisplayName:(NSString *)displayName
{
    return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];
}
// 為上面自定義 用戶
- (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type
{
    self = [super init];
    if(!self) {
        return nil;
    }
    self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];
    self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];
    self.session.delegate = self;
    self.serviceType = type;
    return self;
}
#pragma mark 宣傳自己
- (void)advertiseForBrowserViewController
{
    [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];
}

- (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info
{
    //
    self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];
    self.advertiser.delegate = self;
    [self.advertiser startAdvertisingPeer];
}

- (void)advertiseForProgrammaticDiscovery
{
    [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];
}

- (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info
{
    //自定義自己,為了讓其他設備搜索到自己
    self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];
    self.advertisingAssistant.delegate = self;
    [self.advertisingAssistant start];
}

- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {
    self.invitationHandler = [invitationHandler copy];
    if(self.inviteBlock) self.inviteBlock(peerID, context);
}

#pragma mark 下面是MCAdvertiserAssistant的兩個代理
- (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant
{
    //TODO implement
}

- (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {
    //TODO implement
}

#pragma mark  掃描其他的設備
- (void)browseForProgrammaticDiscovery
{
    
    self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];
    self.browser.delegate = self;
    [self.browser startBrowsingForPeers];
    
}

#pragma mark MCNearbyServiceBrowserDelegate 
- (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
{
    //TODO implement
}

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
{
    if(self.didFindPeer)
    {
        self.didFindPeer(peerID, info);
    }
}

- (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error
{
    //TODO implement
}

#pragma mark 參加會議  也是會議的代理
//   也是  ----- MCSessionDelegate

//  這是完成會議的結果···
- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error
{
      if(self.resourceFinalOnMainQueue)
    {
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.finalResource)
            {
                self.finalResource(resourceName, peerID, localURL, error);
            }
        }];
    }
    else
    {
        if(self.finalResource)
        {
            self.finalResource(resourceName, peerID, localURL, error);
        }
    }
}
// 這是參加  普通數據的會議
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
    if(self.receiveOnMainQueue)
    {
    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
     if(self.receiveDataBlock){
        self.receiveDataBlock(data, peerID);
            }
        }];
    }
    else
    {
        if(self.receiveDataBlock)
        {
            self.receiveDataBlock(data, peerID);
        }
    }
}
// 這是參加普通流的會議
- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID
{
     if(self.streamBlock)
    {
        self.streamBlock(stream, peerID, streamName);
    }
}
// 這是參加圖片資源的會議
- (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
{
    if(self.resourceStart)
    {
        
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.didStartReceivingResource)
            {
                self.didStartReceivingResource(resourceName, peerID, progress);
            }
        }];
    }
    else
    {
      
        if(self.didStartReceivingResource)
        {
            self.didStartReceivingResource(resourceName, peerID, progress);
        }
    }
}


// 這是不同數據,系那是不同會議時候的狀態

- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
{
    // 這個地方是當兩個藍牙設備一旦連接起來,就會形成的一個會議
    if(self.statusOnMainQueue)
    {
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.connectionStatus)
            {
                self.connectionStatus(peerID, state);
            }
        }];
    }
    else
    {
        if(self.connectionStatus)
        {
            self.connectionStatus(peerID, state);
        }
    }
}



#pragma mark  send And receive
//--------------------------------------------------------------------------------------------//
// 發送消息
// 用戶多個
- (NSError *)sendDataToAllPeers:(NSData *)data
{
    // 普通數據的發送
    return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];
}

- (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode
{
    // 確實進入會議
    NSError *error;
    [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];
    return error;
}

// 用戶確定一個
- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers
{
    return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];
}

- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode
{
    NSError *error;
    [self.session sendData:data toPeers:peers withMode:mode error:&error];
    return error;
}


// 接收消息
- (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock
{
    
    self.receiveDataBlock = [dataBlock copy];
    self.receiveOnMainQueue = mainQueue;
}
//--------------------------------------------------------------------------------------------//

- (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete
{
    // 圖片資源數據的發送
    
    return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];
}

// 用戶連接確定 
- (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status
{
    self.connectionStatus = [status copy];
    self.statusOnMainQueue = mainQueue;
}


#pragma mark 自帶的MCBrowserViewController類
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:^{
        if(self.browserConnected) self.browserConnected();
    }];
}

- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:^{
        if(self.browserCancelled) self.browserCancelled();
    }];
}

- (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled
{
    self.browserConnected = [connected copy];
    self.browserCancelled = [cancelled copy];
    // 注意這個自帶的類
    MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];
    browser.delegate = self;
    [controller presentViewController:browser animated:YES completion:nil];
}

- (NSArray *)connectedPeers
{
    return self.session.connectedPeers;
}

// 邀請某某連接
- (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
{
    self.inviteBlock = [invite copy];
}

- (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected
{
    [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];
}

- (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block
{
    
    self.didStartReceivingResource = [block copy];
    self.resourceStart = mainQueue;
}
// 接收某某資源
- (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block
{
    self.finalResource = [block copy];
    self.resourceFinalOnMainQueue = mainQueue;
}
- (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error
{
    return [self.session startStreamWithName:name toPeer:peerID error:error];
}
// 開始轉化為流
- (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock
{
    self.streamBlock = [streamBlock copy];
}
- (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found
{
    self.didFindPeer = [found copy];
}
#pragma mark  一些斷開的情況
- (void)disconnectSession
{
    [self.session disconnect];
}

- (void)stopAdvertising
{
    [self.advertiser stopAdvertisingPeer];
    [self.advertisingAssistant stop];
}

- (void)stopBrowsing
{
    [self.browser stopBrowsingForPeers];
}

- (BOOL)isConnected {
    return self.session.connectedPeers && self.session.connectedPeers.count > 0;
}

// 是否連接 它
- (void)connectToPeer:(BOOL)connect {
    self.invitationHandler(connect, self.session);
}

- (MCSession *)session {
    return self.currentSession;
}

- (MCPeerID *)firstPeer {
    return self.session.connectedPeers.firstObject;
}

@end

#import BlueSessionManager.h

#define ServiceType @MyService

/*
 MCAdvertiserAssistant   //可以接收,並處理用戶請求連接的響應。沒有回調,會彈出默認的提示框,並處理連接。
 MCNearbyServiceAdvertiser //可以接收,並處理用戶請求連接的響應。但是,這個類會有回調,告知有用戶要與您的設備連接,然後可以自定義提示框,以及自定義連接處理。
 MCNearbyServiceBrowser  //用於搜索附近的用戶,並可以對搜索到的用戶發出邀請加入某個會話中。
 MCPeerID //這表明是一個用戶
 MCSession //啟用和管理Multipeer連接會話中的所有人之間的溝通。 通過Sesion,給別人發送數據。
 */
@interface BlueSessionManager ()
@property(strong, nonatomic) MCSession *currentSession; // 當前會議
@property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣傳助手
@property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服務助手
@property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索藍牙者
@property(strong, nonatomic) MCPeerID *peerID; // 用戶

//  以下都是用到的block
@property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);
@property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);
@property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);
@property(nonatomic, copy) void(^browserConnected)(void);
@property(nonatomic, copy) void(^browserCancelled)(void);
@property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);
@property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);
@property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);
@property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);
@property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);
@property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);
// 各種判斷
@property(nonatomic, assign) BOOL receiveOnMainQueue;
@property(nonatomic, assign) BOOL statusOnMainQueue;
@property(nonatomic, assign) BOOL resourceFinalOnMainQueue;
@property(nonatomic, assign) BOOL resourceStart;
@end
@implementation BlueSessionManager
#pragma mark 初始化自己
- (instancetype)initWithDisplayName:(NSString *)displayName
{
    return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];
}
// 為上面自定義 用戶
- (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type
{
    self = [super init];
    if(!self) {
        return nil;
    }
    self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];
    self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];
    self.session.delegate = self;
    self.serviceType = type;
    return self;
}
#pragma mark 宣傳自己
- (void)advertiseForBrowserViewController
{
    [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];
}

- (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info
{
    //
    self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];
    self.advertiser.delegate = self;
    [self.advertiser startAdvertisingPeer];
}

- (void)advertiseForProgrammaticDiscovery
{
    [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];
}

- (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info
{
    //自定義自己,為了讓其他設備搜索到自己
    self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];
    self.advertisingAssistant.delegate = self;
    [self.advertisingAssistant start];
}

- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {
    self.invitationHandler = [invitationHandler copy];
    if(self.inviteBlock) self.inviteBlock(peerID, context);
}

#pragma mark 下面是MCAdvertiserAssistant的兩個代理
- (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant
{
    //TODO implement
}

- (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {
    //TODO implement
}

#pragma mark  掃描其他的設備
- (void)browseForProgrammaticDiscovery
{
    
    self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];
    self.browser.delegate = self;
    [self.browser startBrowsingForPeers];
    
}

#pragma mark MCNearbyServiceBrowserDelegate 
- (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
{
    //TODO implement
}

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
{
    if(self.didFindPeer)
    {
        self.didFindPeer(peerID, info);
    }
}

- (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error
{
    //TODO implement
}

#pragma mark 參加會議  也是會議的代理
//   也是  ----- MCSessionDelegate

//  這是完成會議的結果···
- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error
{
      if(self.resourceFinalOnMainQueue)
    {
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.finalResource)
            {
                self.finalResource(resourceName, peerID, localURL, error);
            }
        }];
    }
    else
    {
        if(self.finalResource)
        {
            self.finalResource(resourceName, peerID, localURL, error);
        }
    }
}
// 這是參加  普通數據的會議
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
    if(self.receiveOnMainQueue)
    {
    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
     if(self.receiveDataBlock){
        self.receiveDataBlock(data, peerID);
            }
        }];
    }
    else
    {
        if(self.receiveDataBlock)
        {
            self.receiveDataBlock(data, peerID);
        }
    }
}
// 這是參加普通流的會議
- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID
{
     if(self.streamBlock)
    {
        self.streamBlock(stream, peerID, streamName);
    }
}
// 這是參加圖片資源的會議
- (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
{
    if(self.resourceStart)
    {
        
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.didStartReceivingResource)
            {
                self.didStartReceivingResource(resourceName, peerID, progress);
            }
        }];
    }
    else
    {
      
        if(self.didStartReceivingResource)
        {
            self.didStartReceivingResource(resourceName, peerID, progress);
        }
    }
}


// 這是不同數據,系那是不同會議時候的狀態

- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
{
    // 這個地方是當兩個藍牙設備一旦連接起來,就會形成的一個會議
    if(self.statusOnMainQueue)
    {
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.connectionStatus)
            {
                self.connectionStatus(peerID, state);
            }
        }];
    }
    else
    {
        if(self.connectionStatus)
        {
            self.connectionStatus(peerID, state);
        }
    }
}



#pragma mark  send And receive
//--------------------------------------------------------------------------------------------//
// 發送消息
// 用戶多個
- (NSError *)sendDataToAllPeers:(NSData *)data
{
    // 普通數據的發送
    return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];
}

- (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode
{
    // 確實進入會議
    NSError *error;
    [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];
    return error;
}

// 用戶確定一個
- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers
{
    return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];
}

- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode
{
    NSError *error;
    [self.session sendData:data toPeers:peers withMode:mode error:&error];
    return error;
}


// 接收消息
- (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock
{
    
    self.receiveDataBlock = [dataBlock copy];
    self.receiveOnMainQueue = mainQueue;
}
//--------------------------------------------------------------------------------------------//

- (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete
{
    // 圖片資源數據的發送
    
    return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];
}

// 用戶連接確定 
- (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status
{
    self.connectionStatus = [status copy];
    self.statusOnMainQueue = mainQueue;
}


#pragma mark 自帶的MCBrowserViewController類
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:^{
        if(self.browserConnected) self.browserConnected();
    }];
}

- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:^{
        if(self.browserCancelled) self.browserCancelled();
    }];
}

- (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled
{
    self.browserConnected = [connected copy];
    self.browserCancelled = [cancelled copy];
    // 注意這個自帶的類
    MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];
    browser.delegate = self;
    [controller presentViewController:browser animated:YES completion:nil];
}

- (NSArray *)connectedPeers
{
    return self.session.connectedPeers;
}

// 邀請某某連接
- (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
{
    self.inviteBlock = [invite copy];
}

- (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected
{
    [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];
}

- (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block
{
    
    self.didStartReceivingResource = [block copy];
    self.resourceStart = mainQueue;
}
// 接收某某資源
- (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block
{
    self.finalResource = [block copy];
    self.resourceFinalOnMainQueue = mainQueue;
}
- (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error
{
    return [self.session startStreamWithName:name toPeer:peerID error:error];
}
// 開始轉化為流
- (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock
{
    self.streamBlock = [streamBlock copy];
}
- (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found
{
    self.didFindPeer = [found copy];
}
#pragma mark  一些斷開的情況
- (void)disconnectSession
{
    [self.session disconnect];
}

- (void)stopAdvertising
{
    [self.advertiser stopAdvertisingPeer];
    [self.advertisingAssistant stop];
}

- (void)stopBrowsing
{
    [self.browser stopBrowsingForPeers];
}

- (BOOL)isConnected {
    return self.session.connectedPeers && self.session.connectedPeers.count > 0;
}

// 是否連接 它
- (void)connectToPeer:(BOOL)connect {
    self.invitationHandler(connect, self.session);
}

- (MCSession *)session {
    return self.currentSession;
}

- (MCPeerID *)firstPeer {
    return self.session.connectedPeers.firstObject;
}

@end

#import BlueSessionManager.h

#define ServiceType @MyService

/*
 MCAdvertiserAssistant   //可以接收,並處理用戶請求連接的響應。沒有回調,會彈出默認的提示框,並處理連接。
 MCNearbyServiceAdvertiser //可以接收,並處理用戶請求連接的響應。但是,這個類會有回調,告知有用戶要與您的設備連接,然後可以自定義提示框,以及自定義連接處理。
 MCNearbyServiceBrowser  //用於搜索附近的用戶,並可以對搜索到的用戶發出邀請加入某個會話中。
 MCPeerID //這表明是一個用戶
 MCSession //啟用和管理Multipeer連接會話中的所有人之間的溝通。 通過Sesion,給別人發送數據。
 */
@interface BlueSessionManager ()
@property(strong, nonatomic) MCSession *currentSession; // 當前會議
@property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣傳助手
@property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服務助手
@property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索藍牙者
@property(strong, nonatomic) MCPeerID *peerID; // 用戶

//  以下都是用到的block
@property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);
@property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);
@property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);
@property(nonatomic, copy) void(^browserConnected)(void);
@property(nonatomic, copy) void(^browserCancelled)(void);
@property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);
@property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);
@property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);
@property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);
@property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);
@property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);
// 各種判斷
@property(nonatomic, assign) BOOL receiveOnMainQueue;
@property(nonatomic, assign) BOOL statusOnMainQueue;
@property(nonatomic, assign) BOOL resourceFinalOnMainQueue;
@property(nonatomic, assign) BOOL resourceStart;
@end
@implementation BlueSessionManager
#pragma mark 初始化自己
- (instancetype)initWithDisplayName:(NSString *)displayName
{
    return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];
}
// 為上面自定義 用戶
- (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type
{
    self = [super init];
    if(!self) {
        return nil;
    }
    self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];
    self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];
    self.session.delegate = self;
    self.serviceType = type;
    return self;
}
#pragma mark 宣傳自己
- (void)advertiseForBrowserViewController
{
    [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];
}

- (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info
{
    //
    self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];
    self.advertiser.delegate = self;
    [self.advertiser startAdvertisingPeer];
}

- (void)advertiseForProgrammaticDiscovery
{
    [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];
}

- (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info
{
    //自定義自己,為了讓其他設備搜索到自己
    self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];
    self.advertisingAssistant.delegate = self;
    [self.advertisingAssistant start];
}

- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {
    self.invitationHandler = [invitationHandler copy];
    if(self.inviteBlock) self.inviteBlock(peerID, context);
}

#pragma mark 下面是MCAdvertiserAssistant的兩個代理
- (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant
{
    //TODO implement
}

- (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {
    //TODO implement
}

#pragma mark  掃描其他的設備
- (void)browseForProgrammaticDiscovery
{
    
    self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];
    self.browser.delegate = self;
    [self.browser startBrowsingForPeers];
    
}

#pragma mark MCNearbyServiceBrowserDelegate 
- (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
{
    //TODO implement
}

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
{
    if(self.didFindPeer)
    {
        self.didFindPeer(peerID, info);
    }
}

- (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error
{
    //TODO implement
}

#pragma mark 參加會議  也是會議的代理
//   也是  ----- MCSessionDelegate

//  這是完成會議的結果···
- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error
{
      if(self.resourceFinalOnMainQueue)
    {
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.finalResource)
            {
                self.finalResource(resourceName, peerID, localURL, error);
            }
        }];
    }
    else
    {
        if(self.finalResource)
        {
            self.finalResource(resourceName, peerID, localURL, error);
        }
    }
}
// 這是參加  普通數據的會議
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
    if(self.receiveOnMainQueue)
    {
    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
     if(self.receiveDataBlock){
        self.receiveDataBlock(data, peerID);
            }
        }];
    }
    else
    {
        if(self.receiveDataBlock)
        {
            self.receiveDataBlock(data, peerID);
        }
    }
}
// 這是參加普通流的會議
- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID
{
     if(self.streamBlock)
    {
        self.streamBlock(stream, peerID, streamName);
    }
}
// 這是參加圖片資源的會議
- (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
{
    if(self.resourceStart)
    {
        
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.didStartReceivingResource)
            {
                self.didStartReceivingResource(resourceName, peerID, progress);
            }
        }];
    }
    else
    {
      
        if(self.didStartReceivingResource)
        {
            self.didStartReceivingResource(resourceName, peerID, progress);
        }
    }
}


// 這是不同數據,系那是不同會議時候的狀態

- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
{
    // 這個地方是當兩個藍牙設備一旦連接起來,就會形成的一個會議
    if(self.statusOnMainQueue)
    {
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.connectionStatus)
            {
                self.connectionStatus(peerID, state);
            }
        }];
    }
    else
    {
        if(self.connectionStatus)
        {
            self.connectionStatus(peerID, state);
        }
    }
}



#pragma mark  send And receive
//--------------------------------------------------------------------------------------------//
// 發送消息
// 用戶多個
- (NSError *)sendDataToAllPeers:(NSData *)data
{
    // 普通數據的發送
    return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];
}

- (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode
{
    // 確實進入會議
    NSError *error;
    [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];
    return error;
}

// 用戶確定一個
- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers
{
    return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];
}

- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode
{
    NSError *error;
    [self.session sendData:data toPeers:peers withMode:mode error:&error];
    return error;
}


// 接收消息
- (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock
{
    
    self.receiveDataBlock = [dataBlock copy];
    self.receiveOnMainQueue = mainQueue;
}
//--------------------------------------------------------------------------------------------//

- (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete
{
    // 圖片資源數據的發送
    
    return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];
}

// 用戶連接確定 
- (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status
{
    self.connectionStatus = [status copy];
    self.statusOnMainQueue = mainQueue;
}


#pragma mark 自帶的MCBrowserViewController類
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:^{
        if(self.browserConnected) self.browserConnected();
    }];
}

- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:^{
        if(self.browserCancelled) self.browserCancelled();
    }];
}

- (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled
{
    self.browserConnected = [connected copy];
    self.browserCancelled = [cancelled copy];
    // 注意這個自帶的類
    MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];
    browser.delegate = self;
    [controller presentViewController:browser animated:YES completion:nil];
}

- (NSArray *)connectedPeers
{
    return self.session.connectedPeers;
}

// 邀請某某連接
- (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
{
    self.inviteBlock = [invite copy];
}

- (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected
{
    [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];
}

- (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block
{
    
    self.didStartReceivingResource = [block copy];
    self.resourceStart = mainQueue;
}
// 接收某某資源
- (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block
{
    self.finalResource = [block copy];
    self.resourceFinalOnMainQueue = mainQueue;
}
- (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error
{
    return [self.session startStreamWithName:name toPeer:peerID error:error];
}
// 開始轉化為流
- (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock
{
    self.streamBlock = [streamBlock copy];
}
- (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found
{
    self.didFindPeer = [found copy];
}
#pragma mark  一些斷開的情況
- (void)disconnectSession
{
    [self.session disconnect];
}

- (void)stopAdvertising
{
    [self.advertiser stopAdvertisingPeer];
    [self.advertisingAssistant stop];
}

- (void)stopBrowsing
{
    [self.browser stopBrowsingForPeers];
}

- (BOOL)isConnected {
    return self.session.connectedPeers && self.session.connectedPeers.count > 0;
}

// 是否連接 它
- (void)connectToPeer:(BOOL)connect {
    self.invitationHandler(connect, self.session);
}

- (MCSession *)session {
    return self.currentSession;
}

- (MCPeerID *)firstPeer {
    return self.session.connectedPeers.firstObject;
}

@end


.m

#import BlueSessionManager.h

#define ServiceType @MyService

/*
 MCAdvertiserAssistant   //可以接收,並處理用戶請求連接的響應。沒有回調,會彈出默認的提示框,並處理連接。
 MCNearbyServiceAdvertiser //可以接收,並處理用戶請求連接的響應。但是,這個類會有回調,告知有用戶要與您的設備連接,然後可以自定義提示框,以及自定義連接處理。
 MCNearbyServiceBrowser  //用於搜索附近的用戶,並可以對搜索到的用戶發出邀請加入某個會話中。
 MCPeerID //這表明是一個用戶
 MCSession //啟用和管理Multipeer連接會話中的所有人之間的溝通。 通過Sesion,給別人發送數據。
 */
@interface BlueSessionManager ()
@property(strong, nonatomic) MCSession *currentSession; // 當前會議
@property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣傳助手
@property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服務助手
@property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索藍牙者
@property(strong, nonatomic) MCPeerID *peerID; // 用戶

//  以下都是用到的block
@property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);
@property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);
@property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);
@property(nonatomic, copy) void(^browserConnected)(void);
@property(nonatomic, copy) void(^browserCancelled)(void);
@property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);
@property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);
@property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);
@property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);
@property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);
@property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);
// 各種判斷
@property(nonatomic, assign) BOOL receiveOnMainQueue;
@property(nonatomic, assign) BOOL statusOnMainQueue;
@property(nonatomic, assign) BOOL resourceFinalOnMainQueue;
@property(nonatomic, assign) BOOL resourceStart;
@end
@implementation BlueSessionManager
#pragma mark 初始化自己
- (instancetype)initWithDisplayName:(NSString *)displayName
{
    return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];
}
// 為上面自定義 用戶
- (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type
{
    self = [super init];
    if(!self) {
        return nil;
    }
    self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];
    self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];
    self.session.delegate = self;
    self.serviceType = type;
    return self;
}
#pragma mark 宣傳自己
- (void)advertiseForBrowserViewController
{
    [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];
}

- (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info
{
    //
    self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];
    self.advertiser.delegate = self;
    [self.advertiser startAdvertisingPeer];
}

- (void)advertiseForProgrammaticDiscovery
{
    [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];
}

- (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info
{
    //自定義自己,為了讓其他設備搜索到自己
    self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];
    self.advertisingAssistant.delegate = self;
    [self.advertisingAssistant start];
}

- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {
    self.invitationHandler = [invitationHandler copy];
    if(self.inviteBlock) self.inviteBlock(peerID, context);
}

#pragma mark 下面是MCAdvertiserAssistant的兩個代理
- (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant
{
    //TODO implement
}

- (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {
    //TODO implement
}

#pragma mark  掃描其他的設備
- (void)browseForProgrammaticDiscovery
{
    
    self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];
    self.browser.delegate = self;
    [self.browser startBrowsingForPeers];
    
}

#pragma mark MCNearbyServiceBrowserDelegate 
- (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
{
    //TODO implement
}

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
{
    if(self.didFindPeer)
    {
        self.didFindPeer(peerID, info);
    }
}

- (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error
{
    //TODO implement
}

#pragma mark 參加會議  也是會議的代理
//   也是  ----- MCSessionDelegate

//  這是完成會議的結果···
- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error
{
      if(self.resourceFinalOnMainQueue)
    {
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.finalResource)
            {
                self.finalResource(resourceName, peerID, localURL, error);
            }
        }];
    }
    else
    {
        if(self.finalResource)
        {
            self.finalResource(resourceName, peerID, localURL, error);
        }
    }
}
// 這是參加  普通數據的會議
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
    if(self.receiveOnMainQueue)
    {
    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
     if(self.receiveDataBlock){
        self.receiveDataBlock(data, peerID);
            }
        }];
    }
    else
    {
        if(self.receiveDataBlock)
        {
            self.receiveDataBlock(data, peerID);
        }
    }
}
// 這是參加普通流的會議
- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID
{
     if(self.streamBlock)
    {
        self.streamBlock(stream, peerID, streamName);
    }
}
// 這是參加圖片資源的會議
- (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
{
    if(self.resourceStart)
    {
        
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.didStartReceivingResource)
            {
                self.didStartReceivingResource(resourceName, peerID, progress);
            }
        }];
    }
    else
    {
      
        if(self.didStartReceivingResource)
        {
            self.didStartReceivingResource(resourceName, peerID, progress);
        }
    }
}


// 這是不同數據,系那是不同會議時候的狀態

- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
{
    // 這個地方是當兩個藍牙設備一旦連接起來,就會形成的一個會議
    if(self.statusOnMainQueue)
    {
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if(self.connectionStatus)
            {
                self.connectionStatus(peerID, state);
            }
        }];
    }
    else
    {
        if(self.connectionStatus)
        {
            self.connectionStatus(peerID, state);
        }
    }
}



#pragma mark  send And receive
//--------------------------------------------------------------------------------------------//
// 發送消息
// 用戶多個
- (NSError *)sendDataToAllPeers:(NSData *)data
{
    // 普通數據的發送
    return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];
}

- (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode
{
    // 確實進入會議
    NSError *error;
    [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];
    return error;
}

// 用戶確定一個
- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers
{
    return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];
}

- (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode
{
    NSError *error;
    [self.session sendData:data toPeers:peers withMode:mode error:&error];
    return error;
}


// 接收消息
- (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock
{
    
    self.receiveDataBlock = [dataBlock copy];
    self.receiveOnMainQueue = mainQueue;
}
//--------------------------------------------------------------------------------------------//

- (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete
{
    // 圖片資源數據的發送
    
    return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];
}

// 用戶連接確定 
- (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status
{
    self.connectionStatus = [status copy];
    self.statusOnMainQueue = mainQueue;
}


#pragma mark 自帶的MCBrowserViewController類
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:^{
        if(self.browserConnected) self.browserConnected();
    }];
}

- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:^{
        if(self.browserCancelled) self.browserCancelled();
    }];
}

- (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled
{
    self.browserConnected = [connected copy];
    self.browserCancelled = [cancelled copy];
    // 注意這個自帶的類
    MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];
    browser.delegate = self;
    [controller presentViewController:browser animated:YES completion:nil];
}

- (NSArray *)connectedPeers
{
    return self.session.connectedPeers;
}

// 邀請某某連接
- (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
{
    self.inviteBlock = [invite copy];
}

- (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected
{
    [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];
}

- (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block
{
    
    self.didStartReceivingResource = [block copy];
    self.resourceStart = mainQueue;
}
// 接收某某資源
- (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block
{
    self.finalResource = [block copy];
    self.resourceFinalOnMainQueue = mainQueue;
}
- (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error
{
    return [self.session startStreamWithName:name toPeer:peerID error:error];
}
// 開始轉化為流
- (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock
{
    self.streamBlock = [streamBlock copy];
}
- (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found
{
    self.didFindPeer = [found copy];
}
#pragma mark  一些斷開的情況
- (void)disconnectSession
{
    [self.session disconnect];
}

- (void)stopAdvertising
{
    [self.advertiser stopAdvertisingPeer];
    [self.advertisingAssistant stop];
}

- (void)stopBrowsing
{
    [self.browser stopBrowsingForPeers];
}

- (BOOL)isConnected {
    return self.session.connectedPeers && self.session.connectedPeers.count > 0;
}

// 是否連接 它
- (void)connectToPeer:(BOOL)connect {
    self.invitationHandler(connect, self.session);
}

- (MCSession *)session {
    return self.currentSession;
}

- (MCPeerID *)firstPeer {
    return self.session.connectedPeers.firstObject;
}

@end
最終效果只能真機測試,所以這裡不做演示!

 

 

 

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved