Skip to content

Commit 1cd3402

Browse files
committed
修正 xhzengAIB#153 中提到, 當使用者點擊錄音按鈕立即放開時, 產生 0 秒錄音的問題
1 parent 0f51c7e commit 1cd3402

5 files changed

Lines changed: 136 additions & 64 deletions

File tree

MessageDisplayKit/Classes/Common/XHVoiceRecordHelper.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#import <Foundation/Foundation.h>
1010

11+
typedef BOOL(^XHPrepareRecorderCompletion)();
1112
typedef void(^XHStartRecorderCompletion)();
1213
typedef void(^XHStopRecorderCompletion)();
1314
typedef void(^XHPauseRecorderCompletion)();
@@ -27,7 +28,8 @@ typedef void(^XHPeakPowerForChannel)(float peakPowerForChannel);
2728
@property (nonatomic) float maxRecordTime; // 默认 60秒为最大
2829
@property (nonatomic, readonly) NSTimeInterval currentTimeInterval;
2930

30-
- (void)startRecordingWithPath:(NSString *)path StartRecorderCompletion:(XHStartRecorderCompletion)startRecorderCompletion;
31+
- (void)prepareRecordingWithPath:(NSString *)path prepareRecorderCompletion:(XHPrepareRecorderCompletion)prepareRecorderCompletion;
32+
- (void)startRecordingWithStartRecorderCompletion:(XHStartRecorderCompletion)startRecorderCompletion;
3133
- (void)pauseRecordingWithPauseRecorderCompletion:(XHPauseRecorderCompletion)pauseRecorderCompletion;
3234
- (void)resumeRecordingWithResumeRecorderCompletion:(XHResumeRecorderCompletion)resumeRecorderCompletion;
3335
- (void)stopRecordingWithStopRecorderCompletion:(XHStopRecorderCompletion)stopRecorderCompletion;

MessageDisplayKit/Classes/Common/XHVoiceRecordHelper.m

Lines changed: 58 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -93,57 +93,65 @@ - (void)stopRecord {
9393
[self resetTimer];
9494
}
9595

96-
- (void)startRecordingWithPath:(NSString *)path StartRecorderCompletion:(XHStartRecorderCompletion)startRecorderCompletion {
97-
_isPause = NO;
98-
NSError *error = nil;
99-
100-
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
101-
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&error];
102-
103-
if(error) {
104-
DLog(@"audioSession: %@ %ld %@", [error domain], (long)[error code], [[error userInfo] description]);
105-
return;
106-
}
107-
108-
[audioSession setActive:YES error:&error];
109-
110-
error = nil;
111-
if(error) {
112-
DLog(@"audioSession: %@ %ld %@", [error domain], (long)[error code], [[error userInfo] description]);
113-
return;
114-
}
115-
116-
/*
117-
NSFileManager *fileManager = [NSFileManager defaultManager];
118-
if ([fileManager fileExistsAtPath:self.recordPath]) {
119-
[fileManager removeItemAtPath:self.recordPath error:&error];
120-
if (error) {
121-
NSAssert(@"error", @"删除出错");
96+
- (void)prepareRecordingWithPath:(NSString *)path prepareRecorderCompletion:(XHPrepareRecorderCompletion)prepareRecorderCompletion {
97+
WEAKSELF
98+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
99+
_isPause = NO;
100+
101+
NSError *error = nil;
102+
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
103+
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&error];
104+
if(error) {
105+
DLog(@"audioSession: %@ %ld %@", [error domain], (long)[error code], [[error userInfo] description]);
106+
return;
122107
}
123-
}
124-
*/
125-
126-
NSMutableDictionary * recordSetting = [NSMutableDictionary dictionary];
127-
128-
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
129-
[recordSetting setValue:[NSNumber numberWithFloat:16000.0] forKey:AVSampleRateKey];
130-
[recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
131-
132-
self.recordPath = path;
133-
134-
error = nil;
135-
136-
if (self.recorder) {
137-
[self cancelRecording];
138-
} else {
139-
_recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:self.recordPath] settings:recordSetting error:&error];
140-
_recorder.delegate = self;
141-
[_recorder prepareToRecord];
142-
_recorder.meteringEnabled = YES;
143-
[_recorder recordForDuration:(NSTimeInterval) 160];
144-
[self startBackgroundTask];
145-
}
146-
108+
109+
error = nil;
110+
[audioSession setActive:YES error:&error];
111+
if(error) {
112+
DLog(@"audioSession: %@ %ld %@", [error domain], (long)[error code], [[error userInfo] description]);
113+
return;
114+
}
115+
116+
NSMutableDictionary * recordSetting = [NSMutableDictionary dictionary];
117+
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
118+
[recordSetting setValue:[NSNumber numberWithFloat:16000.0] forKey:AVSampleRateKey];
119+
[recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
120+
121+
if (weakSelf) {
122+
STRONGSELF
123+
strongSelf.recordPath = path;
124+
error = nil;
125+
126+
if (strongSelf.recorder) {
127+
[strongSelf cancelRecording];
128+
} else {
129+
strongSelf.recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:strongSelf.recordPath] settings:recordSetting error:&error];
130+
strongSelf.recorder.delegate = strongSelf;
131+
[strongSelf.recorder prepareToRecord];
132+
strongSelf.recorder.meteringEnabled = YES;
133+
[strongSelf.recorder recordForDuration:(NSTimeInterval) 160];
134+
[strongSelf startBackgroundTask];
135+
}
136+
137+
if(error) {
138+
DLog(@"audioSession: %@ %ld %@", [error domain], (long)[error code], [[error userInfo] description]);
139+
return;
140+
}
141+
142+
dispatch_async(dispatch_get_main_queue(), ^{
143+
144+
//上層如果傳會來說已經取消了, 那這邊就做原先取消的動作
145+
if (!prepareRecorderCompletion()) {
146+
[strongSelf cancelledDeleteWithCompletion:^{
147+
}];
148+
}
149+
});
150+
}
151+
});
152+
}
153+
154+
- (void)startRecordingWithStartRecorderCompletion:(XHStartRecorderCompletion)startRecorderCompletion {
147155
if ([_recorder record]) {
148156
[self resetTimer];
149157
_timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(updateMeters) userInfo:nil repeats:YES];

MessageDisplayKit/Classes/Controllers/XHMessageTableViewController/XHMessageTableViewController.m

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -929,10 +929,13 @@ - (void)layoutOtherMenuViewHiden:(BOOL)hide {
929929

930930
#pragma mark - Voice Recording Helper Method
931931

932+
- (void)prepareRecordWithCompletion:(XHPrepareRecorderCompletion)completion {
933+
[self.voiceRecordHelper prepareRecordingWithPath:[self getRecorderPath] prepareRecorderCompletion:completion];
934+
}
935+
932936
- (void)startRecord {
933937
[self.voiceRecordHUD startRecordingHUDAtView:self.view];
934-
[self.voiceRecordHelper startRecordingWithPath:[self getRecorderPath] StartRecorderCompletion:^{
935-
938+
[self.voiceRecordHelper startRecordingWithStartRecorderCompletion:^{
936939
}];
937940
}
938941

@@ -1006,6 +1009,11 @@ - (void)didSendFaceAction:(BOOL)sendFace {
10061009
}
10071010
}
10081011

1012+
- (void)prepareRecordingVoiceActionWithCompletion:(BOOL (^)(void))completion {
1013+
DLog(@"prepareRecordingWithCompletion");
1014+
[self prepareRecordWithCompletion:completion];
1015+
}
1016+
10091017
- (void)didStartRecordingVoiceAction {
10101018
DLog(@"didStartRecordingVoice");
10111019
[self startRecord];

MessageDisplayKit/Classes/Views/MessageInputView/XHMessageInputView.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ typedef NS_ENUM(NSInteger, XHMessageInputViewStyle) {
5656
- (void)didSelectedMultipleMediaAction;
5757

5858
/**
59-
* 按下录音按钮开始录音
59+
* 按下錄音按鈕 "準備" 錄音
60+
*/
61+
- (void)prepareRecordingVoiceActionWithCompletion:(BOOL (^)(void))completion;
62+
/**
63+
* 开始录音
6064
*/
6165
- (void)didStartRecordingVoiceAction;
6266
/**

MessageDisplayKit/Classes/Views/MessageInputView/XHMessageInputView.m

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ @interface XHMessageInputView () <UITextViewDelegate>
2727

2828
@property (nonatomic, weak, readwrite) UIButton *holdDownButton;
2929

30+
/**
31+
* 是否取消錄音
32+
*/
33+
@property (nonatomic, assign, readwrite) BOOL isCancelled;
34+
35+
/**
36+
* 是否正在錄音
37+
*/
38+
@property (nonatomic, assign, readwrite) BOOL isRecording;
39+
3040
/**
3141
* 在切换语音和文本消息的时候,需要保存原本已经输入的文本,这样达到一个好的UE
3242
*/
@@ -167,32 +177,72 @@ - (void)messageStyleButtonClicked:(UIButton *)sender {
167177
}
168178

169179
- (void)holdDownButtonTouchDown {
170-
if ([self.delegate respondsToSelector:@selector(didStartRecordingVoiceAction)]) {
171-
[self.delegate didStartRecordingVoiceAction];
180+
self.isCancelled = NO;
181+
self.isRecording = NO;
182+
if ([self.delegate respondsToSelector:@selector(prepareRecordingVoiceActionWithCompletion:)]) {
183+
WEAKSELF
184+
185+
//這邊回調 return 的 YES, 或 NO, 可以讓底層知道該次錄音是否成功, 進而處理無用的 record 對象
186+
[self.delegate prepareRecordingVoiceActionWithCompletion:^BOOL{
187+
STRONGSELF
188+
189+
//這邊要判斷回調回來的時候, 使用者是不是已經早就鬆開手了
190+
if (strongSelf && !strongSelf.isCancelled) {
191+
strongSelf.isRecording = YES;
192+
[strongSelf.delegate didStartRecordingVoiceAction];
193+
return YES;
194+
} else {
195+
return NO;
196+
}
197+
}];
172198
}
173199
}
174200

175201
- (void)holdDownButtonTouchUpOutside {
176-
if ([self.delegate respondsToSelector:@selector(didCancelRecordingVoiceAction)]) {
177-
[self.delegate didCancelRecordingVoiceAction];
202+
203+
//如果已經開始錄音了, 才需要做取消的動作, 否則只要切換 isCancelled, 不讓錄音開始.
204+
if (self.isRecording) {
205+
if ([self.delegate respondsToSelector:@selector(didCancelRecordingVoiceAction)]) {
206+
[self.delegate didCancelRecordingVoiceAction];
207+
}
208+
} else {
209+
self.isCancelled = YES;
178210
}
179211
}
180212

181213
- (void)holdDownButtonTouchUpInside {
182-
if ([self.delegate respondsToSelector:@selector(didFinishRecoingVoiceAction)]) {
183-
[self.delegate didFinishRecoingVoiceAction];
214+
215+
//如果已經開始錄音了, 才需要做結束的動作, 否則只要切換 isCancelled, 不讓錄音開始.
216+
if (self.isRecording) {
217+
if ([self.delegate respondsToSelector:@selector(didFinishRecoingVoiceAction)]) {
218+
[self.delegate didFinishRecoingVoiceAction];
219+
}
220+
} else {
221+
self.isCancelled = YES;
184222
}
185223
}
186224

187225
- (void)holdDownDragOutside {
188-
if ([self.delegate respondsToSelector:@selector(didDragOutsideAction)]) {
189-
[self.delegate didDragOutsideAction];
226+
227+
//如果已經開始錄音了, 才需要做拖曳出去的動作, 否則只要切換 isCancelled, 不讓錄音開始.
228+
if (self.isRecording) {
229+
if ([self.delegate respondsToSelector:@selector(didDragOutsideAction)]) {
230+
[self.delegate didDragOutsideAction];
231+
}
232+
} else {
233+
self.isCancelled = YES;
190234
}
191235
}
192236

193237
- (void)holdDownDragInside {
194-
if ([self.delegate respondsToSelector:@selector(didDragInsideAction)]) {
195-
[self.delegate didDragInsideAction];
238+
239+
//如果已經開始錄音了, 才需要做拖曳回來的動作, 否則只要切換 isCancelled, 不讓錄音開始.
240+
if (self.isRecording) {
241+
if ([self.delegate respondsToSelector:@selector(didDragInsideAction)]) {
242+
[self.delegate didDragInsideAction];
243+
}
244+
} else {
245+
self.isCancelled = YES;
196246
}
197247
}
198248

0 commit comments

Comments
 (0)