主要實現的功能爲:音頻播放,音頻播放時自定義動畫以及音頻時間顯示
一、頭文件和代理添加
在.h文件中添加
#import <AVFoundation/AVFoundation.h>
<AVAudioPlayerDelegate,infoRecordViewDelegate//自定義播放界面的代理>
二、在.h文件中聲明
@property (nonatomic,strong) playRecordView *playRecView;//錄音
@property (nonatomic,strong) UILabel *title;
@property (nonatomic,strong) UIImageView *recordPhoto;
@property (nonatomic,strong) UILabel *lbltime;
@property (nonatomic,strong) UITapGestureRecognizer *tapPlayGesture;//點擊播放手勢
@property (nonatomic,strong) UITapGestureRecognizer *tapCloseGesture;//點擊添加關閉手勢
@property (nonatomic,strong) UITapGestureRecognizer *tapShowGesture;//點擊添加展示手勢
@property (nonatomic,assign) NSInteger countNum;//錄音計時(秒)
@property (nonatomic,strong) NSTimer *playTimer;//控制播放時長顯示更新
@property (nonatomic,strong) NSString *timeString;//播放時間
三、播放界面佈局
#pragma mark - playRecView界面佈局
- (UILabel *)titleInit
{
if (!_title) {
self.title = [[UILabel alloc]init];
self.title.text = @"錄音";
[self addSubview:self.title];
[self.title mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self).offset(0);
make.centerY.mas_equalTo(self.centerY).offset(0);
make.width.mas_equalTo(60);
}];
}
return self.title;
}
- (UIImageView *)recordImageViewInit
{
if (!_recordPhoto) {
// self.recordPhoto = [[UIImageView alloc]init];
// self.recordPhoto.image = [UIImage imageNamed:@"playRecord0.png"];
//自定義動畫
self.recordPhoto = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"playRecord0"]];
// self.recordPhoto.size = CGSizeMake(SCREEN_WIDTH * 0.9 - 10 - 60,SCREEN_HEIGHT * 0.06);
NSArray *picArray = @[[UIImage imageNamed:@"playRecord1"],
[UIImage imageNamed:@"playRecord2"],
[UIImage imageNamed:@"playRecord3"],];
[self.recordPhoto setAnimationImages:picArray];
// self.recordPhoto.contentMode = UIViewContentModeScaleAspectFit;
[self.recordPhoto setAnimationDuration:1.5];
[self.recordPhoto setAnimationRepeatCount:0];
[self addSubview:self.recordPhoto];
[self.recordPhoto mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.title.mas_right).offset(0);
make.centerY.mas_equalTo(self.centerY).offset(0);
make.width.mas_equalTo(SCREEN_WIDTH * 0.9 - 10 - 60);
make.height.mas_equalTo(SCREEN_HEIGHT * 0.06);
}];
}
return self.recordPhoto;
}
- (UILabel *)lbltimeInit
{
if (!_lbltime) {
self.lbltime = [[UILabel alloc]init];
self.lbltime.textColor = MF_ColorFromRGBA2(0x333333, 1);
self.lbltime.text = @"00:00";
[self.lbltime setHidden:YES];
[self addSubview:self.lbltime];
[self.lbltime mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.mas_equalTo(self.recordPhoto.mas_right).offset(0);
make.centerY.mas_equalTo(self.recordPhoto.centerY).offset(0);
make.size.mas_equalTo(CGSizeMake(60, 30));
}];
}
return _lbltime;
}
四、播放界面
在.m文件中添加
#define kSandboxPathStr [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
- (void)viewWillDisappear:(BOOL)animated
{
[self stopAllMusic];
}
- (void)viewDidDisappear:(BOOL)animated
{
//停止播放動畫
[self stopPlayAnimation];
}
#pragma mark - 數據初始化
- (void)setData
{
_tapPlayGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(playRecordGestureClick:)];
self.playRecView = [[playRecordView alloc]init];
self.playRecView.recordPhoto.userInteractionEnabled = YES;
self.playRecView.recordPhoto.tag = 20000 + i;
self.playRecView.tag = 20000 + i;
[[self.playRecView.recordPhoto viewWithTag:20000 + i] addGestureRecognizer:_tapPlayGesture];
self.playRecView.frame = CGRectMake(SCREEN_WIDTH * 0.05, 60 + SCREEN_HEIGHT * 0.08 * i, SCREEN_WIDTH * 0.9 - 10, SCREEN_HEIGHT * 0.08);
[self.recordBackView addSubview:self.playRecView];
}
//播放手勢觸發
- (void)playRecordGestureClick:(UITapGestureRecognizer *)playGesture
{
if(playImageView && playImageView.isAnimating)
{
[_recordView stopAllMusic];
[playImageView stopAnimating];
for (playRecordView *playRecView in _recordBackView.subviews) {
if (playRecView.tag == playImageView.tag) {
[playRecView.lbltime setHidden:YES];
playRecView.lbltime.text = @"00:00";
}
}
[self.playTimer invalidate];
}else{
playImageView = (UIImageView*)playGesture.view;
NSInteger index = playImageView.tag - 20000;
[playImageView startAnimating];
[_recordView playRecord:[self.recordArray objectAtIndex:index]];
//獲取總時間
[self.playTimer fire];
}
NSLog(@"%ld",(long)index);
}
//停止播放動畫代理
- (void)stopPlayAnimation
{
if(playImageView && playImageView.isAnimating)
{
for (playRecordView *playRecView in _recordBackView.subviews) {
if (playRecView.tag == playImageView.tag) {
[playRecView.lbltime setHidden:YES];
playRecView.lbltime.text = @"00:00";
}
}
[self.playTimer invalidate];
[playImageView stopAnimating];
}
}
-(void)sendTotalTime:(NSTimeInterval)totalTime currentTime:(NSTimeInterval)currentTime
{
self.countNum = 0;
NSTimeInterval timeInterval =1 ;
// 1s
self.playTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(updatePlayTimerValue) userInfo:nil repeats:YES];
tduration = totalTime;
}
-(void)updatePlayTimerValue
{
self.countNum += 1;
NSUInteger seconds = (NSUInteger)round(tduration);
_timeString = [NSString stringWithFormat:@"00:%02lu",seconds % 60 - self.countNum];
for (playRecordView *playRecView in _recordBackView.subviews) {
if (playRecView.tag == playImageView.tag) {
[playRecView.lbltime setHidden:NO];
if (self.countNum >= (seconds % 60)) {
playRecView.lbltime.text = @"00:00";
}else{
playRecView.lbltime.text = _timeString;
}
}
}
}
五、recordView(播放方法:核心)
.h文件
@protocol infoRecordViewDelegate<NSObject>
@optional
//獲取錄音數據
-(void)getRecordData:(NSString *)path type:(NSString *)type fileName:(NSString *)fileName;//獲取數據
//停止播放動畫
- (void)stopPlayAnimation;
//發送時間
- (void)sendTotalTime:(NSTimeInterval)totalTime currentTime:(NSTimeInterval)currentTime;
@end
@interface infoRecordView : UIView<AVAudioPlayerDelegate>
@property (nonatomic,strong) AVAudioPlayer *audioPlayer;//音頻播放器
@property (nonatomic,assign) NSInteger countNum;//錄音計時(秒)
@property (nonatomic,strong) NSTimer *playTimer;//控制播放時長顯示更新
@property (nonatomic,strong) NSString *timeString;//播放時間
@property (nonatomic,strong) UIButton *closeBtn; //關閉按鈕
@property (nonatomic,strong) UIView *playBackView;//播放動畫背景
@property (nonatomic,copy) NSString *cafPathStr;
@property (nonatomic,weak) id<infoRecordViewDelegate>delegate;
@property (nonatomic,strong) UIImageView *playAniImageView;//播放動畫
- (void)playRecord:(NSString *)path view:(UIView *)view;
- (void)playRecord:(NSString *)path;
- (void)stopAllMusic;//停止播放
.m文件
#pragma mark - 播放
- (void)playRecord:(NSString *)path view:(UIView *)view
{
[self stopAllMusic];
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; //此處需要恢復設置回放標誌,否則會導致其它播放聲音也會變小
NSString *newPath = [path substringFromIndex:1];//路徑第一位多了個/
[self playMusicWithUrl:[NSURL URLWithString:newPath]];
}
//查看歷史使用
- (void)playRecord:(NSString *)path
{
[self stopAllMusic];
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; //此處需要恢復設置回放標誌,否則會導致其它播放聲音也會變小
NSString *newPath = [path substringFromIndex:1];//路徑第一位多了個/
[self playMusicWithUrl:[NSURL URLWithString:newPath]];
}
- (void)stopPlayRecord
{
[self stopMusicWithUrl:[NSURL URLWithString:self.cafPathStr]];
}
-(void)deleteOldRecordFile{
NSFileManager* fileManager=[NSFileManager defaultManager];
BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:self.cafPathStr];
if (!blHave) {
// NSLog(@"不存在");
return ;
}else {
// NSLog(@"存在");
BOOL blDele= [fileManager removeItemAtPath:self.cafPathStr error:nil];
if (blDele) {
// NSLog(@"刪除成功");
}else {
// NSLog(@"刪除失敗");
}
}
}
-(void)deleteOldRecordFileAtPath:(NSString *)pathStr{
NSFileManager* fileManager=[NSFileManager defaultManager];
BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:pathStr];
if (!blHave) {
// NSLog(@"不存在");
return ;
}else {
// NSLog(@"存在");
BOOL blDele= [fileManager removeItemAtPath:self.cafPathStr error:nil];
if (blDele) {
// NSLog(@"刪除成功");
}else {
// NSLog(@"刪除失敗");
}
}
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
// NSLog(@"delegate--播放完畢----------------------");
//停止播放動畫代理
[self.delegate stopPlayAnimation];
[HUD hide:YES];
}
#pragma mark - AudioPlayer方法
/**
*播放音樂文件
*/
- (BOOL)playMusicWithUrl:(NSURL *)fileUrl
{
//其他播放器停止播放
[self stopAllMusic];
if (!fileUrl) return NO;
AVAudioSession *session=[AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil]; //此處需要恢復設置回放標誌,否則會導致其它播放聲音也會變小
[session setActive:YES error:nil];
NSError *error;
_audioPlayer = [self musices][fileUrl];
#warning 不能加入全局異常斷點,不然會卡在這裏
if (!_audioPlayer) {
//2.2創建播放器
_audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:fileUrl error:&error];
}
_audioPlayer.delegate = self;
if (![_audioPlayer prepareToPlay]){
NSLog(@"緩衝失敗--");
// [self myToast:@"播放器緩衝失敗"];
return NO;
}
if (![_audioPlayer isPlaying]){
//串行同步
dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
[self.delegate sendTotalTime:_audioPlayer.duration currentTime:_audioPlayer.currentTime];
});
dispatch_sync(queue, ^{
//播放
[_audioPlayer play];
});
}
//2.4存入字典
[self musices][fileUrl]=_audioPlayer;
// NSLog(@"musices:%@ musices",self.musices);
return YES;//正在播放,那麼就返回YES
}
/**
*停止播放音樂文件
*/
- (void)stopMusicWithUrl:(NSURL *)fileUrl{
if (!fileUrl) return;//如果沒有傳入文件名,那麼就直接返回
//1.取出對應的播放器
AVAudioPlayer *player=[self musices][fileUrl];
//2.停止
if ([player isPlaying]) {
[player stop];
// NSLog(@"播放結束:%@--------",fileUrl);
}
if ([[self musices].allKeys containsObject:fileUrl]) {
[[self musices] removeObjectForKey:fileUrl];
}
}
//停止所有正在播放的音頻
- (void)stopAllMusic
{
if ([self musices].allKeys.count > 0) {
for ( NSString *playID in [self musices].allKeys) {
AVAudioPlayer *player=[self musices][playID];
[player stop];
}
}
if(HUD){
[HUD hide:YES];
}
}
- (NSMutableDictionary *)musices
{
if (_musices==nil) {
_musices=[NSMutableDictionary dictionary];
}
return _musices;
}
PS:ios錄音功能實現http://blog.csdn.net/fantasy_jun/article/details/77894709