最近有同學問到了關於微信語音連播的問題,在這裡我將自己模仿微信語音連播的核心程式碼部分開源出來,供大家參考。仔細閱讀,按照程式碼的思路就可以實現語音連播。
基本的思路就是:使用遞迴思想。點選語音訊息,獲取cell,判斷(1)播放的訊息是否正在播放,(2)播放的訊息是否是點選的訊息;然後進行播放,更新語音動畫UI。播放完畢,需要在記憶體中的messageArray中查詢下一條訊息,通過訊息找到cell,更新cell上的語音動畫UI,播放該語音,更新資料庫中的標記。然後繼續下一條訊息的播放。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
- (void)clickCellVoice:(VMessageEntity *)model { __weak VChatsViewController *weakSelf = self; // cell 的點選事件, if (model) { VChatVoiceBaseCell *voiceCell = nil; // 在視覺化的cell上面用messageId查詢與model對應的VChatVoiceBaseCell, for (UITableViewCell *cell in [_tableView visibleCells]) { if ([cell isKindOfClass:[VChatVoiceBaseCell class]]) { VChatVoiceBaseCell *tempVoiceCell =(VChatVoiceBaseCell *)cell; if ( tempVoiceCell.message.messageId == model.messageId) { voiceCell = (VChatVoiceBaseCell *)cell; break; } } } if (voiceCell) { //如果點選的cell的語音檔案沒有播放,則開始播放,同時開啟語音播放動畫。 if (![[VAudioPalyerManager sharedManager] isPlaying]) { [voiceCell.playIcon startAnimating]; model.voiceMessage.isPlaying = YES; [[VAudioPalyerManager sharedManager] playWithfile:model.voiceMessage.voicemd5 finishPlaying:^(NSString *fileName,BOOL isFinished) { // 播放完成的回撥,停止動畫,開始播放下一條 [voiceCell.playIcon stopAnimating]; model.voiceMessage.isPlaying = NO; if (isFinished) { if (model.messageStatus == VMessageStatusNone && model.readStatus == VMessageNoRead) { [weakSelf playNextUnReadVoiceWithMessageEntity:model]; } } }]; }else if([[VAudioPalyerManager sharedManager]isPlaying] &&![model.voiceMessage.voicemd5 isEqualToString:[[VAudioPalyerManager sharedManager] currentFileName]]) //如果正在播放,且與當前的檔名不同,停止播放當前的播放效果,播放另外一條。 { [[VAudioPalyerManager sharedManager] stop]; [voiceCell.playIcon startAnimating]; model.voiceMessage.isPlaying = YES; [[VAudioPalyerManager sharedManager] playWithfile:model.voiceMessage.voicemd5 finishPlaying:^(NSString *fileName, BOOL isFinish) { [voiceCell.playIcon stopAnimating]; model.voiceMessage.isPlaying = NO; if (isFinish) { if (model.messageStatus == VMessageStatusNone && model.readStatus == VMessageNoRead) { [weakSelf playNextUnReadVoiceWithMessageEntity:model]; } } }]; }else if([[VAudioPalyerManager sharedManager]isPlaying] && [model.voiceMessage.voicemd5 isEqualToString:[[VAudioPalyerManager sharedManager] currentFileName]]) // 處理當前正在播放的語音,停止當前的語音播放 { [[VAudioPalyerManager sharedManager] stop]; model.voiceMessage.isPlaying = NO; if([voiceCell.playIcon isAnimating]) { [voiceCell.playIcon stopAnimating]; } } } } } //遞迴查詢下一條未讀語音訊息 - (void)playNextUnReadVoiceWithMessageEntity:(VMessageEntity *)model { //找到message在chatArray裡面的位置 model.readStatus = VMessageHaveRead; __weak VChatsViewController *weakSelf = self; if (model) { NSIndexPath *index = [NSIndexPath indexPathForRow: [self.messageArray indexOfObject:model] inSection:0]; if (index) { for (NSInteger i = index.row+1; i < self.messageArray.count; i++) { id tempObj = self.messageArray[i]; if ([tempObj isKindOfClass:[VMessageEntity class]]) { VMessageEntity *messageEntity = (VMessageEntity *)tempObj; if (messageEntity.messageType == VMessageTypeVoice && messageEntity.messageStatus == VMessageStatusNone) {//判斷是語音訊息 if (messageEntity.readStatus == VMessageNoRead) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //取到下一條的cell VChatVoiceReceiveCell *voiceBaseCell = nil; for (UITableView *cell in [_tableView visibleCells]) { if ([cell isKindOfClass:[VChatVoiceReceiveCell class]]) { VChatVoiceReceiveCell *tempBaseCell = (VChatVoiceReceiveCell *)cell; if (tempBaseCell.message.messageId == messageEntity.messageId) { voiceBaseCell = (VChatVoiceReceiveCell *)cell;//找到cell } } } //找到cell,更新UI [voiceBaseCell.playIcon startAnimating]; //更新資料庫訊息的未讀狀態,去掉未讀標記 [voiceBaseCell receiveVoiceCellBeClick]; //更新資料庫 [[VMessageManager sharedManager] updateReadStatusWithClientMessageId: messageEntity.clientMessageId readStatus:VMessageHaveRead userId:messageEntity.sendUserId]; messageEntity.readStatus = VMessageHaveRead; [weakSelf.messageArray replaceObjectAtIndex:i withObject:messageEntity]; //進行播放 messageEntity.voiceMessage.isPlaying = YES; [[VAudioPalyerManager sharedManager] playWithfile:messageEntity.voiceMessage.voicemd5 finishPlaying:^(NSString *fileName, BOOL isFinish) { [voiceBaseCell.playIcon stopAnimating]; messageEntity.voiceMessage.isPlaying = NO; if (isFinish) { if (model.messageStatus == VMessageStatusNone) { //isFinish == yes 則完整播放,再次呼叫這個方法 [weakSelf playNextUnReadVoiceWithMessageEntity:model]; } } }]; }); break; } } }else{ NSLog(@"不是訊息型別"); } } } } } |