// // recordViewController.m // 双子星云手机 // // Created by xd h on 2025/3/28. // #import "recordViewController.h" #import "recordBottomView.h" #import "recordingView.h" #import #import "recordFileModel.h" #import "recordFileCell.h" @interface recordViewController () @property (nonatomic, strong) UITableView *tableView; @property(nonatomic,strong)NSMutableArray *audioArr;//音频数据 @property(nonatomic,strong)recordBottomView *recordBottomV;//底部视图 @property(nonatomic,strong)recordingView *recordingV;//录音中 @end @implementation recordViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. _audioArr = [NSMutableArray new]; [self drawAnyView]; [self getRecordDataFun]; } - (void)drawAnyView { [self.view setBackgroundColor:HWF5F7FAColor]; self.navBarBGView.hidden = NO; [self.navigationBar setHidden:YES]; [self.toolBar setHidden:YES]; [self.titleLabel setText:NSLocalizedString(@"mine_record_title",nil)]; //底部视图 _recordBottomV = [[recordBottomView alloc] init]; [self.view addSubview:_recordBottomV]; [_recordBottomV mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0.f); make.right.mas_equalTo(0.f); make.bottom.mas_equalTo(0.f); make.height.mas_equalTo(100.f + AdaptTabHeight); }]; KWeakSelf _recordBottomV.didClickRecordFun = ^{ [weakSelf didClickRecordFun]; }; [self.view addSubview:self.tableView]; [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0); make.right.mas_equalTo(0); make.bottom.equalTo(self.recordBottomV.mas_top).offset(0.f); //make.bottom.mas_equalTo(0); make.top.equalTo(self.navBarBGView.mas_bottom).offset(10.f); }]; } #pragma mark - 懒加载 - (UITableView *)tableView{ if (!_tableView) { _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_W, SCREEN_H - TABBARHEIGHT) style:UITableViewStylePlain]; _tableView.delegate = self; _tableView.dataSource = self; _tableView.showsVerticalScrollIndicator = NO; _tableView.showsHorizontalScrollIndicator = NO; // _tableView.contentInset = UIEdgeInsetsMake(-H_STATE_BAR, 0, 0, 0); [_tableView setSeparatorStyle:(UITableViewCellSeparatorStyleNone)]; [_tableView setSeparatorColor:[UIColor clearColor]]; [_tableView setBackgroundColor:[UIColor clearColor]]; [_tableView setTableFooterView:[UIView new]]; [_tableView setBounces:YES]; if (@available(iOS 15.0, *)) { _tableView.sectionHeaderTopPadding = 0; } //空数据引入第三方开源处理 _tableView.emptyDataSetSource = self; _tableView.emptyDataSetDelegate = self; // 下拉追加 // MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ // [self getMoreNetWorkData]; // }]; // // NSString *text = NSLocalizedString(@"NAS_bottom_tip",nil); // [footer setTitle:text forState:MJRefreshStateNoMoreData]; // _tableView.mj_footer = footer; } return _tableView; } #pragma mark - 列表委托 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ if(!_audioArr){ return 0; } return _audioArr.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 1; } - (recordFileCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ __block NSInteger row = indexPath.section; static NSString *identifier = @"recordFileCell"; recordFileCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier]; cell.selectionStyle = UITableViewCellSelectionStyleNone; if (!cell){ cell = [[recordFileCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier]; [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; [cell setBackgroundColor:[UIColor clearColor]]; [cell setAccessoryType:(UITableViewCellAccessoryNone)]; } if(row < _audioArr.count){ recordFileModel* dataModel = _audioArr[row]; cell.curRecordFileModel = dataModel; // // KWeakSelf // cell.didClickSwitch = ^(BOOL SwitchOn) { // //if([weakSelf userCheckFileModel:dataModel withShowTip:YES]){ // [weakSelf userCheckFilePreviewByRow:row]; // //} // }; } return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ NSInteger row = indexPath.section; if(row >=_audioArr.count){ return 0.0; } recordFileModel *model = _audioArr[row]; if (model.showAllType) { return 150; } return 65; } - (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { return [UIView new]; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ return 12.0; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger row = indexPath.section; if(row < _audioArr.count){ recordFileModel *model = _audioArr[row]; if(!model.showAllType){ model.showAllType = YES; [tableView reloadData]; } } } #pragma mark 空数据 - (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView { NSString *imageName = @"common_no_data_pic"; return [UIImage imageNamed:imageName]; } - (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView { NSString *text = NSLocalizedString(@"record_no_data_tip",nil); NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:16.0f], NSForegroundColorAttributeName: HW999999Color}; return [[NSAttributedString alloc] initWithString:text attributes:attributes]; } //调整图片位置 - (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView { return -150; } #pragma mark 读取本地数据 - (void)getRecordDataFun { NSString *documentsDirectory = kSHPath_Record; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error = nil; NSArray *fileList = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:&error]; if (error) { HLog(@"Error reading contents of directory: %@", error.localizedDescription); } [_audioArr removeAllObjects]; BOOL isFirstType = YES; for (NSString *fileName in fileList) { NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName]; // 获取文件属性 NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:filePath error:&error]; if (error) { NSLog(@"获取文件属性出错: %@ - %@", fileName, error.localizedDescription); error = nil; continue; } // 判断是否是目录 BOOL isDirectory = [fileAttributes[NSFileType] isEqualToString:NSFileTypeDirectory]; // 获取文件大小 unsigned long long fileSize = [fileAttributes[NSFileSize] unsignedLongLongValue]; recordFileModel *model = [recordFileModel new]; model.fileName = fileName; model.filePath = filePath; model.fileSize = fileSize; model.isDirectory = isDirectory; model.modificationDate = fileAttributes[NSFileModificationDate] ?: [NSDate date]; NSURL *fileUrl = [NSURL URLWithString:model.filePath]; NSTimeInterval time = [self getDurationOfAudioFile:fileUrl]; model.totalTime = (NSInteger)ceil(time); // 结果为 5; if (isFirstType) { model.showAllType = YES; isFirstType = NO; } else{ model.showAllType = NO; } // 创建文件信息字典 // NSDictionary *fileInfo = @{ // @"name": fileName, // @"path": filePath, // @"size": @(fileSize), // @"isDirectory": @(isDirectory), // @"modificationDate": fileAttributes[NSFileModificationDate] ?: [NSDate date] // }; [_audioArr addObject:model]; } } #pragma mark 获取录音文件的时长 - (NSTimeInterval)getDurationOfAudioFile:(NSURL *)fileURL { NSError *error; AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error]; if (error) { HLog(@"Error: %@", error.localizedDescription); return 0; } return player.duration; } #pragma mark 点击了录音 - (void)didClickRecordFun { if(_recordingV){ return; } //检测麦克风权限 AVAudioSessionRecordPermission permissionStatus = [[AVAudioSession sharedInstance] recordPermission]; // MicrophonePermissionStatus status; // switch (permissionStatus) { // case AVAudioSessionRecordPermissionUndetermined: // status = MicrophonePermissionStatusNotDetermined; // break; // case AVAudioSessionRecordPermissionDenied: // status = MicrophonePermissionStatusDenied; // break; // case AVAudioSessionRecordPermissionGranted: // status = MicrophonePermissionStatusGranted; // break; // } if (permissionStatus == AVAudioSessionRecordPermissionDenied) { NSString *tip = NSLocalizedString(@"mine_record_microphone_tip",nil); [[iToast makeText:tip] show]; return; } else if(permissionStatus == AVAudioSessionRecordPermissionUndetermined) { KWeakSelf [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) { dispatch_async(dispatch_get_main_queue(), ^{ if (granted) { [weakSelf beginRecordFun]; } else { } }); }]; return; } [self beginRecordFun]; } #pragma mark 弹起录音功能 - (void)beginRecordFun { _recordingV = [[recordingView alloc] init]; [ksharedAppDelegate.window addSubview:_recordingV]; [_recordingV mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0.f); make.right.mas_equalTo(0.f); make.bottom.mas_equalTo(0.f); make.top.mas_equalTo(0); }]; NSInteger index = _audioArr.count + 1; [_recordingV beginRecordFunWith:index]; KWeakSelf _recordingV.didClickRecordEndFun = ^{ [weakSelf deleteRecordingViewFun]; }; } #pragma mark 删除录音中界面 - (void)deleteRecordingViewFun { [_recordingV removeFromSuperview]; _recordingV = nil; [self getRecordDataFun]; [self.tableView reloadData]; } @end