我是在別人的demo基礎上繼續做的,百度cui ios ,博客園的那個,那人博客寫的相當仔細,大家想學的更多可以去他博客看看
原demo只有錄音界面,然后錄音結束自動播放的功能。
錄音界面我稍微改了下,本身是錄音結束就自動播放,我是選擇了在別的界面播放。然后是取路徑命名的問題,我改為了用當前時間命名。原demo是用myRecord.caf作為結尾命名,因為原demo錄完就播放嘛。
錄音界面有個列表按鈕,跳到第二個界面,可看到具體的錄音欄目。然后點擊右側的按鈕,進入第三個頁面自動播放,然后是暫停繼續等等
第三個頁面自動播放,其實就是把創建音頻播放器對象寫在了load里,然后調用下音頻會話,跟第一個界面的東西基本一樣的思路。
然后還有一個關鍵點是第二個界面點按鈕跳轉的時候,你必須知道你點的是第幾行,也就是你點的是哪個錄音,把這個路徑送到第三個界面給音頻對象用,這個采用單例模式實現跨界面傳值。
還有就是頁面間的跳轉,一種直接拉線,一種是用代碼,我的隨筆里也寫了用代碼的。
界面設計
錄音界面代碼
1 #import "ViewController.h" 2 #import <AVFoundation/AVFoundation.h> 3 4 @interface ViewController ()<AVAudioRecorderDelegate> 5 6 @property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音頻錄音機 7 @property (nonatomic,strong) AVAudioPlayer *audioPlayer;//音頻播放器,用於播放錄音文件 8 @property (nonatomic,strong) NSTimer *timer;//錄音聲波監控(注意這里暫時不對播放進行監控) 9 10 @property (weak, nonatomic) IBOutlet UIButton *record;//開始錄音 11 @property (weak, nonatomic) IBOutlet UIButton *pause;//暫停錄音 12 @property (weak, nonatomic) IBOutlet UIButton *resume;//恢復錄音 13 @property (weak, nonatomic) IBOutlet UIButton *stop;//停止錄音 14 @property (weak, nonatomic) IBOutlet UIProgressView *audioPower;//音頻波動 15 @property (weak, nonatomic) IBOutlet UIButton *exit;//退出 16 17 @end 18 19 @implementation ViewController 20 21 #pragma mark - 控制器視圖方法 22 - (void)viewDidLoad { 23 //f改變progressview的長寬 24 _audioPower.transform=CGAffineTransformMakeScale(1.0f,4.0f); 25 [super viewDidLoad]; 26 //自動播放的 27 [self setAudioSession]; 28 } 29 30 #pragma mark - 私有方法 31 32 33 34 /** 35 * 取得錄音文件保存路徑 36 * 37 * @return 錄音文件路徑 38 */ 39 -(NSURL *)getSavePath{ 40 //獲取文件路徑 41 NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 42 NSLog(@"%@",urlStr); 43 NSDate *date=[NSDate date]; 44 NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 45 [dateFormatter setDateFormat:@"yyyy-MM-dd-HH:mm:ss"]; 46 //NSDate轉NSString 47 NSString *sss = [dateFormatter stringFromDate:date]; 48 NSString *ccc=[sss stringByAppendingString:@".caf"]; 49 urlStr=[urlStr stringByAppendingPathComponent:ccc]; 50 NSURL *url=[NSURL fileURLWithPath:urlStr]; 51 // NSLog(@"第一個頁面的路徑",url); 52 return url; 53 } 54 55 /** 56 * 取得錄音文件設置 57 * 58 * @return 錄音設置 59 */ 60 -(NSDictionary *)getAudioSetting{ 61 NSMutableDictionary *dicM=[NSMutableDictionary dictionary]; 62 //設置錄音格式 63 [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey]; 64 //設置錄音采樣率,8000是電話采樣率,對於一般錄音已經夠了 65 [dicM setObject:@(8000) forKey:AVSampleRateKey]; 66 //設置通道,這里采用單聲道 67 [dicM setObject:@(1) forKey:AVNumberOfChannelsKey]; 68 //每個采樣點位數,分為8、16、24、32 69 [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey]; 70 //是否使用浮點數采樣 71 [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey]; 72 //....其他設置等 73 return dicM; 74 } 75 76 /** 77 * 獲得錄音機對象 78 * 79 * @return 錄音機對象 80 */ 81 -(AVAudioRecorder *)audioRecorder{ 82 if (!_audioRecorder) { 83 //創建錄音文件保存路徑 84 NSURL *url=[self getSavePath]; 85 //創建錄音格式設置 86 NSDictionary *setting=[self getAudioSetting]; 87 //創建錄音機 88 NSError *error=nil; 89 _audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error]; 90 _audioRecorder.delegate=self; 91 _audioRecorder.meteringEnabled=YES;//如果要監控聲波則必須設置為YES 92 if (error) { 93 NSLog(@"創建錄音機對象時發生錯誤,錯誤信息:%@",error.localizedDescription); 94 return nil; 95 } 96 } 97 return _audioRecorder; 98 } 99 -(void)setAudioSession{ 100 AVAudioSession *audioSession=[AVAudioSession sharedInstance]; 101 //設置為錄音狀態 102 [audioSession setCategory:AVAudioSessionCategoryRecord error:nil]; 103 [audioSession setActive:YES error:nil]; 104 }/** 105 * 錄音聲波監控定制器 106 * 107 * @return 定時器 108 */ 109 -(NSTimer *)timer{ 110 if (!_timer) { 111 //創建一個定時器 112 _timer=[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(audioPowerChange) userInfo:nil repeats:YES]; 113 } 114 return _timer; 115 }; 116 117 /** 118 * 錄音聲波狀態設置 119 */ 120 -(void)audioPowerChange{ 121 [self.audioRecorder updateMeters];//更新測量值 122 float power= [self.audioRecorder averagePowerForChannel:0];//取得第一個通道的音頻,注意音頻強度范圍時-160到0 123 CGFloat progress=(1.0/160.0)*(power+160.0); 124 [self.audioPower setProgress:progress]; 125 }; 126 #pragma mark - UI事件 127 /** 128 * 點擊錄音按鈕 129 * 130 * @param sender 錄音按鈕 131 */ 132 - (IBAction)recordBu:(UIButton *)sender { 133 if (![self.audioRecorder isRecording]) { 134 [self.audioRecorder record];//首次使用應用時如果調用record方法會詢問用戶是否允許使用麥克風,需要在info.plist加權限 135 //創建一個定時器 136 self.timer.fireDate=[NSDate distantPast]; 137 } 138 }; 139 140 /** 141 * 點擊暫定按鈕 142 * 143 * @param sender 暫停按鈕 144 */ 145 - (IBAction)pauseBu:(UIButton *)sender { 146 if ([self.audioRecorder isRecording]) { 147 [self.audioRecorder pause]; 148 self.timer.fireDate=[NSDate distantFuture]; 149 NSLog(@"錄音暫停"); 150 } 151 }; 152 153 /** 154 * 點擊恢復按鈕 155 * 恢復錄音只需要再次調用record,AVAudioSession會幫助你記錄上次錄音位置並追加錄音 156 * 157 * @param sender 恢復按鈕 158 */ 159 - (IBAction)resumeBu:(UIButton *)sender { 160 [self recordBu:sender]; 161 NSLog(@"錄音繼續"); 162 }; 163 164 /** 165 * 點擊停止按鈕 166 * 167 * @param sender 停止按鈕 168 */ 169 - (IBAction)stopBu:(UIButton *)sender { 170 [self.audioRecorder stop]; 171 self.timer.fireDate=[NSDate distantFuture]; 172 self.audioPower.progress=0.0; 173 NSLog(@"錄音文件路徑%@",[self getSavePath]); 174 }; 175 /** 176 177 退出 178 */ 179 -(IBAction)exitBu:(UIButton *)sender{ 180 exit(0); 181 }; 182 #pragma mark - 錄音機代理方法 183 /** 184 * 錄音完成,錄音完成后播放錄音 185 * 186 * @param recorder 錄音機對象 187 * @param flag 是否成功 188 */ 189 /* 190 -(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{ 191 if (![self.audioPlayer isPlaying]) { 192 [self.audioPlayer play]; 193 } 194 NSLog(@"錄音完成!"); 195 }; 196 */ 197 @end
列表界面代碼
9 #import "ViewController2.h" 10 #import <Foundation/Foundation.h> 11 #import <AVFoundation/AVFoundation.h> 12 #import "ViewController3.h" 13 #import "Single.h" 14 @interface ViewController2 () <AVAudioRecorderDelegate,UITableViewDelegate,UITableViewDataSource> 15 //,UITableViewDelegate, UITableViewDataSource> 16 //tableView 17 @property (strong, nonatomic) IBOutlet UITableView *recoderTableView; 18 19 @property (strong,nonatomic ) IBOutlet UIButton *remove; 20 21 22 23 24 @end 25 26 27 @implementation ViewController2 28 29 - (void)viewDidLoad { 30 [super viewDidLoad]; 31 self.recoderTableView.dataSource=self; 32 33 } 34 35 //返回數組共下面的方法調用 36 -(NSMutableArray *)getFileList{ 37 NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 38 NSFileManager *fileManager = [NSFileManager defaultManager]; 39 //將doc下面的文件,以caf為后綴的全部存入數組 40 // NSMutableArray *ss=[fileManager enumeratorAtPath:urlStr]; 41 NSMutableArray *ss=[fileManager contentsOfDirectoryAtPath:urlStr error:nil]; 42 return ss; 43 // NSString *file; 44 /* for(int i=0;i<[ss count];i++) 45 while(file=[ss indexOfObject:i]) 46 { 47 if([[file pathExtension] isEqual:@".caf"]) 48 { 49 [fileList addObject:file]; 50 //看file是否有信息 51 NSLog(@"%@",file); 52 } 53 }*/ 54 } 55 //tableView 的相關方法 56 //告訴控件分為幾組 57 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 58 { 59 return 1; 60 } 61 //告訴UI每組顯示幾行數據,section參數表示第幾組,只有1組,那么section為0 62 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 63 { 64 //一組數據,返回存儲文件名稱的數組長度 65 return [[self getFileList]count]; 66 } 67 //告訴控件每組的每行顯示什么單元格內容 68 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath 69 { 70 UITableViewCell *cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 71 //右側的按鈕 72 cell.accessoryType=UITableViewCellAccessoryDetailButton; 73 74 //獲取存了文件信息的數組然后遍歷賦值到cell文本中 75 NSMutableArray *ss=[self getFileList]; 76 for(int i=0;i<[tableView numberOfRowsInSection:0];i++) 77 { 78 // indexPath.section==0 79 //控制每行的 80 if( indexPath.row==i) 81 cell.textLabel.text=[ss objectAtIndex:i]; 82 } 83 return cell; 84 85 } 86 #pragma ui控件操作 87 -(IBAction)deleteBU:(UIButton *)sender{ 88 //setedit animate讓tableView進入可編輯模式 89 [_recoderTableView setEditing:!_recoderTableView.isEditing animated:true]; 90 } 91 //對tableView自帶刪除功能的方法實現 92 -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 93 { 94 95 if (editingStyle == UITableViewCellEditingStyleDelete) {//刪除 96 NSFileManager *fileM=[NSFileManager new]; 97 NSString *newUrl2=[self cellItemPath:indexPath]; 98 [fileM removeItemAtPath:newUrl2 error:nil]; 99 // sing.singleCase=toUrl; 100 [self.recoderTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];//刪除刷新 101 } 102 103 } 104 //tableView右側的點擊跳轉,需要將URL通過單例對象送到第三個頁面 105 - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath 106 { 107 NSString *newUrl2=[self cellItemPath:indexPath]; 108 NSURL *toUrl=[[NSURL alloc]initFileURLWithPath:newUrl2]; 109 NSLog(@"頁面二准備復制給單例對象的URL是%@",toUrl); 110 [Single sharedInstance].value=toUrl; 111 //跳轉代碼 112 UIViewController *next = [[self storyboard] instantiateViewControllerWithIdentifier:@"ViewController3"]; 113 [self presentModalViewController:next animated:NO]; 114 115 } 116 //cell中拿到每行文件的信息,並且拼裝成完整的路徑,供刪除當前行方法,和點擊當前行跳轉方法使用 117 -(NSString *)cellItemPath:(NSIndexPath *)indexPath{ 118 NSFileManager *fileM=[NSFileManager new]; 119 NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 120 // NSString *newStr=urlStr+indexPath.row; 121 NSArray *newArr=[fileM contentsOfDirectoryAtPath:urlStr error:nil]; 122 //行數 123 int i=indexPath.row; 124 //接收要刪除的元素 125 NSString *newPro; 126 for(int j=0;j<[newArr count];j++) 127 { 128 if(j==i) 129 { 130 newPro= [newArr objectAtIndex:i]; 131 } 132 } 133 //重新拼接路徑,路徑文件夾名+/+要刪除 的文件名 134 NSString *newUrl=[urlStr stringByAppendingString:@"/"]; 135 NSString *newUrl2=[newUrl stringByAppendingString:newPro]; 136 return newUrl2; 137 } 138 139 140 141 @end
播放界面代碼
#import "ViewController3.h" #import <AVFoundation/AVFoundation.h> #import "ViewController.h" #import "ViewController2.h" #import "Single.h" @interface ViewController3 ()<AVAudioRecorderDelegate> @property (nonatomic,strong) NSTimer *timer; //聲波監控,對播放進行監控 @property (weak, nonatomic) IBOutlet UIProgressView *audioPower;//音頻波動 @property (nonatomic,strong) AVAudioPlayer *audioPlayer;//音頻播放器,用於播放錄音文件 @property (weak,nonatomic ) IBOutlet UIButton *pause;//暫停 @property (weak,nonatomic ) IBOutlet UIButton *conti;//繼續 @property (weak,nonatomic ) IBOutlet UIButton *back;//返回 //通過單例對象拿到第二個控制器的cell對象傳的URL @property (nonatomic,copy) NSURL *url; @property (weak, nonatomic) IBOutlet UIButton *exit0; @end @implementation ViewController3 - (void)viewDidLoad { [super viewDidLoad]; _url=[Single sharedInstance].value; NSLog(@"頁面三%@",_url); if(!_audioPlayer){ _audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:_url error:nil]; _audioPlayer.numberOfLoops=0; [_audioPlayer prepareToPlay]; //開啟定時器 self.timer.fireDate=[NSDate distantPast]; } [self setAudioSession];
[self.audioPlayer play]; } /** * 設置音頻會話 */ -(void)setAudioSession{ AVAudioSession *audioSession=[AVAudioSession sharedInstance]; //設置為播放狀態 [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; } /** * 錄音聲波監控定制器 * * @return 定時器 */ -(NSTimer *)timer{ if (!_timer) { //創建一個定時器 _timer=[NSTimer scheduledTimerWithTimeInterval:0.5f target:self selector:@selector(audioPowerChange) userInfo:nil repeats:YES]; } return _timer; }; /** * 播放聲波狀態設置 */ -(void)audioPowerChange{ float progress= self.audioPlayer.currentTime /self.audioPlayer.duration; [self.audioPower setProgress:progress animated:true]; }; #pragma UI操作 //退出 -(IBAction)exitBu:(UIButton *)sender{ exit(0); }; //返回 -(IBAction)backBu:(UIButton *)sender{ UIViewController *next = [[self storyboard] instantiateViewControllerWithIdentifier:@"ViewController2"]; [self presentModalViewController:next animated:NO]; }; //暫停 -(IBAction)pauseBu:(UIButton *)sender { [self.audioPlayer pause]; self.timer.fireDate=[NSDate distantFuture]; }; //繼續 -(IBAction)contiBu:(UIButton *)sender{ [self.audioPlayer play]; self.timer.fireDate=[NSDate distantPast]; } @end
還有個單例類存URL的代碼,這個我寫過了,在隨筆里