recordViewController.m 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. //
  2. // recordViewController.m
  3. // 双子星云手机
  4. //
  5. // Created by xd h on 2025/3/28.
  6. //
  7. #import "recordViewController.h"
  8. #import "recordBottomView.h"
  9. #import "recordingView.h"
  10. #import <AVFoundation/AVFoundation.h>
  11. #import "recordFileModel.h"
  12. #import "recordFileCell.h"
  13. #import "reNameRecordFileView.h"
  14. #import "ComontAlretViewController.h"
  15. #import "editTypeHeadView.h"
  16. #import "recordEditBottomView.h"
  17. #import "uploadFileRecordViewController.h"
  18. @interface recordViewController ()<UITableViewDelegate,UITableViewDataSource,DZNEmptyDataSetSource, DZNEmptyDataSetDelegate,AVAudioPlayerDelegate>
  19. @property (nonatomic, strong) UIButton *rightButton;//编辑
  20. @property(nonatomic,strong) editTypeHeadView*curEditTypeHeadView;
  21. @property(nonatomic,strong) recordEditBottomView*curEditTypeBottomView;
  22. @property(nonatomic,strong) NSMutableArray* didSelectListArr;
  23. @property(nonatomic,assign) BOOL isEditType;
  24. @property (nonatomic, strong) UITableView *tableView;
  25. @property(nonatomic,strong)NSMutableArray *audioArr;//音频数据
  26. @property(nonatomic,strong)recordBottomView *recordBottomV;//底部视图
  27. @property(nonatomic,strong)recordingView *recordingV;//录音中
  28. @property(nonatomic,strong)reNameRecordFileView * reNameRecordFileV;
  29. @property(nonatomic,strong)AVAudioPlayer * curAudioPlayer;//音频播放器
  30. @property (strong, nonatomic) NSTimer *progressTimer;
  31. @property(nonatomic,strong) recordFileModel* curPlayerModel;//当前播放的音频数据
  32. @end
  33. @implementation recordViewController
  34. - (void)viewDidLoad {
  35. [super viewDidLoad];
  36. // Do any additional setup after loading the view.
  37. _audioArr = [NSMutableArray new];
  38. _didSelectListArr = [NSMutableArray new];
  39. [self drawAnyView];
  40. [self getRecordDataFun];
  41. }
  42. - (void)viewDidDisappear:(BOOL)animated
  43. {
  44. [super viewDidDisappear:animated];
  45. if (_progressTimer) {
  46. [_progressTimer invalidate];
  47. _progressTimer = nil;
  48. }
  49. }
  50. - (void)drawAnyView
  51. {
  52. [self.view setBackgroundColor:HWF5F7FAColor];
  53. self.navBarBGView.hidden = NO;
  54. [self.navigationBar setHidden:YES];
  55. [self.toolBar setHidden:YES];
  56. [self.titleLabel setText:NSLocalizedString(@"mine_record_title",nil)];
  57. self.navBarBGView.backgroundColor = [UIColor whiteColor];
  58. //编辑
  59. _rightButton = [[UIButton alloc] init];
  60. [_rightButton setTitle:NSLocalizedString(@"edit_common",nil) forState:UIControlStateNormal];
  61. [_rightButton setTitleColor:[UIColor hwColor:@"#01B7EA"] forState:UIControlStateNormal];
  62. _rightButton.titleLabel.font = [UIFont systemFontOfSize:14.0];
  63. _rightButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
  64. [_rightButton addTarget:self action:@selector(didClickEditFun) forControlEvents:UIControlEventTouchUpInside];
  65. [self.navBarBGView addSubview:_rightButton];
  66. [_rightButton mas_makeConstraints:^(MASConstraintMaker *make) {
  67. make.right.mas_equalTo(-15.f);
  68. make.width.mas_equalTo(40.f);
  69. make.centerY.equalTo(self.titleLabel.mas_centerY).offset(0.0);
  70. make.height.mas_equalTo(30);
  71. }];
  72. _curEditTypeHeadView = [[editTypeHeadView alloc] init];
  73. _curEditTypeHeadView.hidden = YES;
  74. [self.navBarBGView addSubview:_curEditTypeHeadView];
  75. [_curEditTypeHeadView mas_makeConstraints:^(MASConstraintMaker *make) {
  76. make.left.mas_equalTo(0);
  77. make.right.mas_equalTo(0);
  78. make.bottom.mas_equalTo(0);
  79. make.height.mas_equalTo(NAVIHEIGHT - AdaptNaviHeight);
  80. }];
  81. #pragma mark 编辑状态的 取消 和全选按钮 响应事件
  82. KWeakSelf
  83. _curEditTypeHeadView.didClickButtonFun = ^(NSInteger tag) {
  84. if(tag==1){
  85. [weakSelf userCancelEditTypeFun];
  86. }
  87. };
  88. _curEditTypeHeadView.didClickSelectAllFun = ^(UIButton * _Nonnull but) {
  89. [weakSelf didClickSelectAllButton:but];
  90. };
  91. _curEditTypeBottomView = [[recordEditBottomView alloc] init];
  92. _curEditTypeBottomView.hidden = YES;
  93. [self.view addSubview:_curEditTypeBottomView];
  94. [_curEditTypeBottomView mas_makeConstraints:^(MASConstraintMaker *make) {
  95. make.left.mas_equalTo(0);
  96. make.right.mas_equalTo(0);
  97. make.bottom.mas_equalTo(0);
  98. make.height.mas_equalTo(60 + AdaptTabHeight);
  99. }];
  100. #pragma mark 编辑状态的 下载 删除 响应事件
  101. _curEditTypeBottomView.didClickButtonFun = ^(NSInteger tag) {
  102. if(tag==1){
  103. [weakSelf gotoUpLoadFileFun];
  104. }
  105. else if(tag==3){
  106. [weakSelf showDeleteAlearViewFun];
  107. }
  108. };
  109. //底部视图
  110. _recordBottomV = [[recordBottomView alloc] init];
  111. [self.view addSubview:_recordBottomV];
  112. [_recordBottomV mas_makeConstraints:^(MASConstraintMaker *make) {
  113. make.left.mas_equalTo(0.f);
  114. make.right.mas_equalTo(0.f);
  115. make.bottom.mas_equalTo(0.f);
  116. make.height.mas_equalTo(100.f + AdaptTabHeight);
  117. }];
  118. //KWeakSelf
  119. _recordBottomV.didClickRecordFun = ^{
  120. [weakSelf didClickRecordFun];
  121. };
  122. [self.view addSubview:self.tableView];
  123. [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
  124. make.left.mas_equalTo(0);
  125. make.right.mas_equalTo(0);
  126. make.bottom.equalTo(self.recordBottomV.mas_top).offset(0.f);
  127. //make.bottom.mas_equalTo(0);
  128. make.top.equalTo(self.navBarBGView.mas_bottom).offset(10.f);
  129. }];
  130. }
  131. #pragma mark - 懒加载
  132. - (UITableView *)tableView{
  133. if (!_tableView) {
  134. _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_W, SCREEN_H - TABBARHEIGHT) style:UITableViewStylePlain];
  135. _tableView.delegate = self;
  136. _tableView.dataSource = self;
  137. _tableView.showsVerticalScrollIndicator = NO;
  138. _tableView.showsHorizontalScrollIndicator = NO;
  139. // _tableView.contentInset = UIEdgeInsetsMake(-H_STATE_BAR, 0, 0, 0);
  140. [_tableView setSeparatorStyle:(UITableViewCellSeparatorStyleNone)];
  141. [_tableView setSeparatorColor:[UIColor clearColor]];
  142. [_tableView setBackgroundColor:[UIColor clearColor]];
  143. [_tableView setTableFooterView:[UIView new]];
  144. [_tableView setBounces:YES];
  145. if (@available(iOS 15.0, *)) {
  146. _tableView.sectionHeaderTopPadding = 0;
  147. }
  148. //空数据引入第三方开源处理
  149. _tableView.emptyDataSetSource = self;
  150. _tableView.emptyDataSetDelegate = self;
  151. // 下拉追加
  152. // MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{
  153. // [self getMoreNetWorkData];
  154. // }];
  155. //
  156. // NSString *text = NSLocalizedString(@"NAS_bottom_tip",nil);
  157. // [footer setTitle:text forState:MJRefreshStateNoMoreData];
  158. // _tableView.mj_footer = footer;
  159. }
  160. return _tableView;
  161. }
  162. #pragma mark - 列表委托
  163. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
  164. if(!_audioArr){
  165. return 0;
  166. }
  167. return _audioArr.count;
  168. }
  169. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  170. return 1;
  171. }
  172. - (recordFileCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  173. __block NSInteger row = indexPath.section;
  174. static NSString *identifier = @"recordFileCell";
  175. recordFileCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier];
  176. cell.selectionStyle = UITableViewCellSelectionStyleNone;
  177. if (!cell){
  178. cell = [[recordFileCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
  179. [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
  180. [cell setBackgroundColor:[UIColor clearColor]];
  181. [cell setAccessoryType:(UITableViewCellAccessoryNone)];
  182. }
  183. if(row < _audioArr.count){
  184. recordFileModel* dataModel = _audioArr[row];
  185. cell.curRecordFileModel = dataModel;
  186. KWeakSelf
  187. cell.didClickRecordButFun = ^(NSInteger index) {
  188. [weakSelf didClickCellFunBy:index withRow:row];
  189. };
  190. cell.didClickSwitch = ^(BOOL SwitchOn) {
  191. [weakSelf userCheckFilePreviewByRow:row];
  192. };
  193. }
  194. return cell;
  195. }
  196. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
  197. NSInteger row = indexPath.section;
  198. if(row >=_audioArr.count){
  199. return 0.0;
  200. }
  201. recordFileModel *model = _audioArr[row];
  202. if (model.showAllType) {
  203. return 150;
  204. }
  205. return 65;
  206. }
  207. - (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
  208. {
  209. return [UIView new];
  210. }
  211. - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
  212. return 12.0;
  213. }
  214. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  215. {
  216. if (_isEditType) {
  217. return;
  218. }
  219. NSInteger row = indexPath.section;
  220. if(row < _audioArr.count){
  221. recordFileModel *model = _audioArr[row];
  222. if(!model.showAllType){
  223. model.showAllType = YES;
  224. [tableView reloadData];
  225. }
  226. }
  227. }
  228. #pragma mark 空数据
  229. - (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView {
  230. NSString *imageName = @"common_no_data_pic";
  231. return [UIImage imageNamed:imageName];
  232. }
  233. - (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView {
  234. NSString *text = NSLocalizedString(@"record_no_data_tip",nil);
  235. NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:16.0f],
  236. NSForegroundColorAttributeName: HW999999Color};
  237. return [[NSAttributedString alloc] initWithString:text attributes:attributes];
  238. }
  239. //调整图片位置
  240. - (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView {
  241. return -150;
  242. }
  243. #pragma mark 读取本地数据
  244. - (void)getRecordDataFun
  245. {
  246. NSString *documentsDirectory = kSHPath_Record;
  247. NSFileManager *fileManager = [NSFileManager defaultManager];
  248. NSError *error = nil;
  249. NSArray *fileList = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:&error];
  250. if (error) {
  251. HLog(@"Error reading contents of directory: %@", error.localizedDescription);
  252. }
  253. NSMutableArray *dataArr = [NSMutableArray new];
  254. //BOOL isFirstType = YES;
  255. for (NSString *fileName in fileList) {
  256. NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
  257. // 获取文件属性
  258. NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:filePath error:&error];
  259. if (error) {
  260. NSLog(@"获取文件属性出错: %@ - %@", fileName, error.localizedDescription);
  261. error = nil;
  262. continue;
  263. }
  264. // 判断是否是目录
  265. BOOL isDirectory = [fileAttributes[NSFileType] isEqualToString:NSFileTypeDirectory];
  266. // 获取文件大小
  267. unsigned long long fileSize = [fileAttributes[NSFileSize] unsignedLongLongValue];
  268. recordFileModel *model = [recordFileModel new];
  269. model.fileName = fileName;
  270. model.filePath = filePath;
  271. model.fileSize = fileSize;
  272. model.isDirectory = isDirectory;
  273. model.modificationDate = fileAttributes[NSFileModificationDate] ?: [NSDate date];
  274. NSURL *fileUrl = [NSURL URLWithString:model.filePath];
  275. NSTimeInterval time = [self getDurationOfAudioFile:fileUrl];
  276. model.totalTime = (NSInteger)ceil(time); // 结果为 5;
  277. model.showAllType = NO;
  278. // if (isFirstType) {
  279. // model.showAllType = YES;
  280. // isFirstType = NO;
  281. // }
  282. // else{
  283. // model.showAllType = NO;
  284. // }
  285. // 创建文件信息字典
  286. // NSDictionary *fileInfo = @{
  287. // @"name": fileName,
  288. // @"path": filePath,
  289. // @"size": @(fileSize),
  290. // @"isDirectory": @(isDirectory),
  291. // @"modificationDate": fileAttributes[NSFileModificationDate] ?: [NSDate date]
  292. // };
  293. [dataArr addObject:model];
  294. }
  295. // 假设你的对象有一个名为 dateProperty 的 NSDate 属性
  296. NSArray *sortedArray = [dataArr sortedArrayUsingComparator:^NSComparisonResult(recordFileModel* obj1, recordFileModel* obj2) {
  297. return [obj2.modificationDate compare:obj1.modificationDate];
  298. }];
  299. [_audioArr removeAllObjects];
  300. [_audioArr addObjectsFromArray:sortedArray];
  301. recordFileModel *firstModel = _audioArr.firstObject;
  302. firstModel.showAllType = YES;
  303. }
  304. #pragma mark 获取录音文件的时长
  305. - (NSTimeInterval)getDurationOfAudioFile:(NSURL *)fileURL {
  306. NSError *error;
  307. AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
  308. if (error) {
  309. HLog(@"Error: %@", error.localizedDescription);
  310. return 0;
  311. }
  312. return player.duration;
  313. }
  314. #pragma mark 点击了录音
  315. - (void)didClickRecordFun
  316. {
  317. if(_recordingV){
  318. return;
  319. }
  320. if(_curAudioPlayer){
  321. [self audioPlayerPauseFun];
  322. }
  323. //检测麦克风权限
  324. AVAudioSessionRecordPermission permissionStatus = [[AVAudioSession sharedInstance] recordPermission];
  325. // MicrophonePermissionStatus status;
  326. // switch (permissionStatus) {
  327. // case AVAudioSessionRecordPermissionUndetermined:
  328. // status = MicrophonePermissionStatusNotDetermined;
  329. // break;
  330. // case AVAudioSessionRecordPermissionDenied:
  331. // status = MicrophonePermissionStatusDenied;
  332. // break;
  333. // case AVAudioSessionRecordPermissionGranted:
  334. // status = MicrophonePermissionStatusGranted;
  335. // break;
  336. // }
  337. if (permissionStatus == AVAudioSessionRecordPermissionDenied) {
  338. NSString *tip = NSLocalizedString(@"mine_record_microphone_tip",nil);
  339. [[iToast makeText:tip] show];
  340. return;
  341. }
  342. else if(permissionStatus == AVAudioSessionRecordPermissionUndetermined) {
  343. KWeakSelf
  344. [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
  345. dispatch_async(dispatch_get_main_queue(), ^{
  346. if (granted) {
  347. [weakSelf beginRecordFun];
  348. } else {
  349. }
  350. });
  351. }];
  352. return;
  353. }
  354. [self beginRecordFun];
  355. }
  356. #pragma mark 弹起录音功能
  357. - (void)beginRecordFun
  358. {
  359. _recordingV = [[recordingView alloc] init];
  360. [ksharedAppDelegate.window addSubview:_recordingV];
  361. [_recordingV mas_makeConstraints:^(MASConstraintMaker *make) {
  362. make.left.mas_equalTo(0.f);
  363. make.right.mas_equalTo(0.f);
  364. make.bottom.mas_equalTo(0.f);
  365. make.top.mas_equalTo(0);
  366. }];
  367. NSInteger index = _audioArr.count + 1;
  368. [_recordingV beginRecordFunWith:index];
  369. KWeakSelf
  370. _recordingV.didClickRecordEndFun = ^{
  371. [weakSelf deleteRecordingViewFun];
  372. };
  373. }
  374. #pragma mark 删除录音中界面
  375. - (void)deleteRecordingViewFun
  376. {
  377. [_recordingV removeFromSuperview];
  378. _recordingV = nil;
  379. [self getRecordDataFun];
  380. [self.tableView reloadData];
  381. }
  382. #pragma mark 点击cell里面的按钮事件 //index 1 编辑 2 删除 10 播放(100 暂停) 11 后退 12 前进
  383. - (void)didClickCellFunBy:(NSInteger)index withRow:(NSInteger)row
  384. {
  385. switch (index) {
  386. case 1:
  387. [self didClickEditFunWithRow:row];
  388. break;
  389. case 2:
  390. [self deleteFileByRow:row];
  391. break;
  392. case 10:
  393. [self didClickPlayerByRow:row];
  394. break;
  395. case 11:
  396. [self playerBackwardFun];
  397. break;
  398. case 12:
  399. [self playerForwardFun];
  400. break;
  401. case 100://
  402. [self audioPlayerPauseFun];
  403. break;
  404. default:
  405. break;
  406. }
  407. }
  408. #pragma mark 点击编辑
  409. - (void)didClickEditFunWithRow:(NSInteger)row
  410. {
  411. recordFileModel *model = nil;
  412. if (_audioArr.count > row) {
  413. model = _audioArr[row];
  414. }
  415. else{
  416. return;
  417. }
  418. if (_reNameRecordFileV) {
  419. [_reNameRecordFileV removeFromSuperview];
  420. }
  421. _reNameRecordFileV = [[reNameRecordFileView alloc] init];
  422. [ksharedAppDelegate.window addSubview:_reNameRecordFileV];
  423. _reNameRecordFileV.fileName = model.fileName;
  424. [_reNameRecordFileV mas_makeConstraints:^(MASConstraintMaker *make) {
  425. make.left.mas_equalTo(0.0);
  426. make.right.mas_equalTo(0.0);
  427. make.top.mas_equalTo(0.0);
  428. make.bottom.mas_equalTo(0.0);
  429. }];
  430. KWeakSelf
  431. _reNameRecordFileV.didClickOkButtonFun = ^(NSString * _Nonnull newName) {
  432. [weakSelf checkRenameByNewName:newName withRow:row];
  433. };
  434. }
  435. #pragma mark 重命名逻辑
  436. - (void)checkRenameByNewName:(NSString*)newName withRow:(NSInteger)row
  437. {
  438. [_reNameRecordFileV removeFromSuperview];
  439. if (!newName || newName.length == 0) {
  440. NSString *tip = NSLocalizedString(@"record_reName_error_tip",nil);
  441. [[iToast makeText:tip] show];
  442. return;
  443. }
  444. recordFileModel *model = nil;
  445. if (_audioArr.count > row) {
  446. model = _audioArr[row];
  447. }
  448. else{
  449. return;
  450. }
  451. BOOL isRepeatType = NO;
  452. for (int i=0; i<_audioArr.count; i++) {
  453. if (i != row) {
  454. recordFileModel *preModel = _audioArr[i];
  455. if ([preModel.fileName isEqualToString:newName]) {
  456. isRepeatType = YES;
  457. break;
  458. }
  459. }
  460. }
  461. if (isRepeatType) {
  462. NSString *tip = NSLocalizedString(@"record_reName_error_repeat_tip",nil);
  463. [[iToast makeText:tip] show];
  464. return;
  465. }
  466. //[_reNameRecordFileV removeFromSuperview];
  467. // 获取文件管理器
  468. NSFileManager *fileManager = [NSFileManager defaultManager];
  469. // 原始文件路径
  470. NSString *documentsPath = kSHPath_Record;
  471. NSString *oldFilePath = [documentsPath stringByAppendingPathComponent:model.fileName];
  472. // 新文件路径
  473. NSString *newFilePath = [documentsPath stringByAppendingPathComponent:newName];
  474. NSError *error = nil;
  475. // 重命名/移动文件
  476. BOOL success = [fileManager moveItemAtPath:oldFilePath toPath:newFilePath error:&error];
  477. if (!success) {
  478. NSString *tip = NSLocalizedString(@"record_reName_error_title",nil);
  479. [[iToast makeText:tip] show];
  480. } else {
  481. NSString *tip = NSLocalizedString(@"record_reName_ok_title",nil);
  482. [[iToast makeText:tip] show];
  483. model.fileName = newName;
  484. [_tableView reloadData];
  485. }
  486. }
  487. #pragma mark 文件删除弹框
  488. - (void)showDeleteAlearViewFun
  489. {
  490. [self deleteFileByRow:-1];
  491. }
  492. #pragma mark 文件删除
  493. - (void)deleteFileByRow:(NSInteger)row
  494. {
  495. KWeakSelf
  496. /*弹窗提示重启*/
  497. ComontAlretViewController *nextVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"delete_file_title_msg",nil)
  498. msg:NSLocalizedString(@"delete_file_tip_msg",nil)
  499. imageStr:@""
  500. cancelTitle:NSLocalizedString(@"other_cancel",nil)
  501. okTitle:NSLocalizedString(@"delete_file_title_msg",nil) isOkBtnHighlight:YES
  502. didClickOk:^{
  503. [weakSelf sureDeleteFileByRow:row];
  504. } didClickCancel:^{
  505. }];
  506. nextVC.modalPresentationStyle = UIModalPresentationCustom;
  507. [self presentViewController:nextVC animated:YES completion:^{
  508. nextVC.view.superview.backgroundColor = [UIColor clearColor];
  509. }];
  510. }
  511. #pragma mark 文件删除
  512. - (void)sureDeleteFileByRow:(NSInteger)row
  513. {
  514. if (row == -1) {//删除编辑状态选中的旋转
  515. [self deleteSelectFileFun];
  516. return;
  517. }
  518. recordFileModel *model = nil;
  519. if (_audioArr.count > row) {
  520. model = _audioArr[row];
  521. }
  522. else{
  523. return;
  524. }
  525. NSFileManager *fileManager = [NSFileManager defaultManager];
  526. NSString *filePath = model.filePath; // 获取要删除的文件路径
  527. NSError *error = nil;
  528. BOOL success = [fileManager removeItemAtPath:filePath error:&error];
  529. if (!success) {
  530. //NSLog(@"删除文件失败: %@", error.localizedDescription);
  531. [[iToast makeText:NSLocalizedString(@"record_deleteFile_fail",nil)] show];
  532. } else {
  533. //NSLog(@"文件删除成功");
  534. [[iToast makeText:NSLocalizedString(@"delete_file_suc_msg",nil)] show];
  535. [_audioArr removeObject:model];
  536. recordFileModel *firstModel = _audioArr.firstObject;
  537. firstModel.showAllType = YES;
  538. [_tableView reloadData];
  539. }
  540. }
  541. #pragma mark 删除编辑状态选中的旋转
  542. - (void)deleteSelectFileFun
  543. {
  544. NSFileManager *fileManager = [NSFileManager defaultManager];
  545. for (recordFileModel*delModel in _didSelectListArr) {
  546. NSString *filePath = delModel.filePath; // 获取要删除的文件路径
  547. NSError *error = nil;
  548. BOOL success = [fileManager removeItemAtPath:filePath error:&error];
  549. if (!success) {
  550. //NSLog(@"删除文件失败: %@", error.localizedDescription);
  551. //[[iToast makeText:NSLocalizedString(@"record_deleteFile_fail",nil)] show];
  552. } else {
  553. //NSLog(@"文件删除成功");
  554. //[[iToast makeText:NSLocalizedString(@"delete_file_suc_msg",nil)] show];
  555. [_audioArr removeObject:delModel];
  556. }
  557. }
  558. // recordFileModel *firstModel = _audioArr.firstObject;
  559. // firstModel.showAllType = YES;
  560. [_tableView reloadData];
  561. [[iToast makeText:NSLocalizedString(@"delete_file_suc_msg",nil)] show];
  562. [_didSelectListArr removeAllObjects];
  563. [self setEditTypeTitleFun];
  564. }
  565. #pragma mark 点击了编辑按钮
  566. - (void)didClickEditFun
  567. {
  568. _isEditType = YES;
  569. _curEditTypeHeadView.hidden = NO;
  570. _curEditTypeBottomView.hidden = NO;
  571. _recordBottomV.hidden = YES;
  572. [self setEditTypeTitleFun];
  573. for (recordFileModel*model in _audioArr) {
  574. model.showAllType = NO;
  575. model.isEditType = YES;
  576. }
  577. [self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
  578. make.left.mas_equalTo(0);
  579. make.right.mas_equalTo(0);
  580. make.bottom.mas_equalTo(_curEditTypeBottomView.mas_top);
  581. make.top.equalTo(self.navBarBGView.mas_bottom).offset(10.f);
  582. }];
  583. [self.tableView reloadData];
  584. }
  585. #pragma mark 用户取消编辑编辑
  586. - (void)userCancelEditTypeFun
  587. {
  588. //数据还原
  589. for (recordFileModel*model in _didSelectListArr) {
  590. model.isSelectType = NO;
  591. }
  592. [_didSelectListArr removeAllObjects];
  593. for (recordFileModel*model in _audioArr) {
  594. model.isEditType = NO;
  595. }
  596. recordFileModel*firstModel = _audioArr.firstObject;
  597. firstModel.showAllType = YES;
  598. _isEditType = NO;
  599. [self.tableView reloadData];
  600. _curEditTypeHeadView.hidden = YES;
  601. _curEditTypeBottomView.hidden = YES;
  602. _recordBottomV.hidden = NO;
  603. [self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
  604. make.left.mas_equalTo(0);
  605. make.right.mas_equalTo(0);
  606. make.bottom.equalTo(self.recordBottomV.mas_top).offset(0.f);
  607. make.top.equalTo(self.navBarBGView.mas_bottom).offset(10.f);;
  608. }];
  609. }
  610. - (void)didClickSelectAllButton:(UIButton*)button
  611. {
  612. //button.selected = !button.selected;
  613. [_didSelectListArr removeAllObjects];
  614. for (recordFileModel* dataModel in _audioArr) {
  615. if(!button.selected){
  616. dataModel.isSelectType = button.selected;
  617. }
  618. else{
  619. [_didSelectListArr addObject:dataModel];
  620. dataModel.isSelectType = button.selected;
  621. }
  622. }
  623. [self.tableView reloadData];
  624. [self setEditTypeTitleFun];
  625. }
  626. - (void)userCheckFilePreviewByRow:(NSInteger)row
  627. {
  628. if(row < _audioArr.count){
  629. recordFileModel* dataModel = _audioArr[row];
  630. if(dataModel.isSelectType){
  631. [_didSelectListArr removeObject:dataModel];
  632. }
  633. else{
  634. [_didSelectListArr addObject:dataModel];
  635. }
  636. dataModel.isSelectType = !dataModel.isSelectType;
  637. [self setEditTypeTitleFun];
  638. }
  639. }
  640. #pragma mark 设置选中标题
  641. - (void)setEditTypeTitleFun
  642. {
  643. [_curEditTypeHeadView setTitleLabetextByNumbers:_didSelectListArr.count];
  644. if (_didSelectListArr.count > 0) {
  645. [_curEditTypeBottomView setButtonStateFunBy:YES];
  646. }
  647. else{
  648. [_curEditTypeBottomView setButtonStateFunBy:NO];
  649. }
  650. }
  651. #pragma mark 处理上传
  652. - (void)gotoUpLoadFileFun{
  653. if (_didSelectListArr.count <= 0) {
  654. return;
  655. }
  656. uploadFileRecordViewController *vc = [uploadFileRecordViewController new];
  657. [self.navigationController pushViewController:vc animated:YES];
  658. vc.isUploadingType = YES;
  659. [vc gotoUploadFileByRecord:_didSelectListArr];
  660. }
  661. #pragma mark 音频播放相关
  662. - (void)didClickPlayerByRow:(NSInteger)row
  663. {
  664. if(row > _audioArr.count){
  665. return;
  666. }
  667. recordFileModel* dataModel = _audioArr[row];
  668. NSURL* fileURL = [NSURL URLWithString:dataModel.filePath];
  669. _curPlayerModel = dataModel;
  670. for (recordFileModel*model in _audioArr) {
  671. model.isPlayingType = NO;
  672. }
  673. _curPlayerModel.isPlayingType = YES;
  674. if (_curAudioPlayer) {
  675. [_curAudioPlayer stop];
  676. _curAudioPlayer = nil;
  677. }
  678. NSError *error;
  679. _curAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
  680. _curAudioPlayer.delegate = self;
  681. _curAudioPlayer.currentTime = _curPlayerModel.curPlayerTime;
  682. [_curAudioPlayer play];//播放
  683. [self startProgressTimer];
  684. }
  685. #pragma mark 音频暂停播放
  686. - (void)audioPlayerPauseFun
  687. {
  688. [_curAudioPlayer pause];
  689. [self stopProgressTimer];
  690. }
  691. #pragma mark 播放代理
  692. - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
  693. {
  694. HLog(@"播放完成")
  695. [self stopProgressTimer];
  696. _curPlayerModel.isPlayingType = NO;
  697. _curPlayerModel.curPlayerTime = 0;// _curPlayerModel.totalTime;
  698. [self.tableView reloadData];
  699. }
  700. - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error
  701. {
  702. if (error) {
  703. HLog(@"解码失败")
  704. }
  705. }
  706. #pragma mark 播放进度相关
  707. - (void)startProgressTimer {
  708. [self stopProgressTimer];
  709. self.progressTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
  710. target:self
  711. selector:@selector(updateProgress)
  712. userInfo:nil
  713. repeats:YES];
  714. }
  715. - (void)stopProgressTimer {
  716. [self.progressTimer invalidate];
  717. self.progressTimer = nil;
  718. }
  719. - (void)updateProgress {
  720. if (_curPlayerModel.totalTime > _curPlayerModel.curPlayerTime) {
  721. _curPlayerModel.curPlayerTime += 1;
  722. }
  723. [self.tableView reloadData];
  724. }
  725. #pragma mark 向前15秒
  726. - (void)playerForwardFun
  727. {
  728. _curPlayerModel.curPlayerTime += 15;
  729. if (_curPlayerModel.curPlayerTime > _curPlayerModel.totalTime) {
  730. _curPlayerModel.curPlayerTime = _curPlayerModel.totalTime -2;
  731. }
  732. _curAudioPlayer.currentTime = _curPlayerModel.curPlayerTime;
  733. [self.tableView reloadData];
  734. }
  735. #pragma mark 向后15秒
  736. - (void)playerBackwardFun
  737. {
  738. _curPlayerModel.curPlayerTime -= 15;
  739. if (_curPlayerModel.curPlayerTime < 0) {
  740. _curPlayerModel.curPlayerTime = 0;
  741. }
  742. _curAudioPlayer.currentTime = _curPlayerModel.curPlayerTime;
  743. [self.tableView reloadData];
  744. }
  745. @end