iOS开发中音频工具类的封装以及音乐播放器的细节控制

这篇文章主要介绍了iOS开发中音频工具类的封装以及音乐播放器的细节控制,代码基于传统的Objective-C,需要的朋友可以参考下

一、控制器间数据传递

两个控制器之间数据的传递
第一种方法:
代码如下:

self.parentViewController.music=self.music[indexPath.row];

不能满足
第二种做法:把整个数组传递给它
第三种做法:设置一个数据源,设置播放控制器的数据源是这个控制器。self.parentViewController.dataSource=self;好处:没有耦合性,任何实现了协议的可以作为数据源。
第四种做法:把整个项目会使用到的音频资源交给一个工具类去管理,这样就不用传递过去了。直接向工具类索要资源就可以。

感谢观看:

朋友赠送一份最新iOS面试题,收集了一些自己认为不错的资料和大家分享给大家,交流群文件自取!!

点击获取文件:https://jq.qq.com/?_wv=1027&k=VGob8c0B

二、封装一个音频工具类

新建一个音频工具类,用来管理音乐数据(音乐模型)

iOS开发中音频工具类的封装以及音乐播放器的细节控制

工具类中的代码设计如下:

代码如下:

 YYMusicTool.h文件
//
//  YYMusicTool.h
//

#import <Foundation/Foundation.h>
@class YYMusicModel;
@interface YYMusicTool : NSObject
/**
 *  返回所有的歌曲
 */
+ (NSArray *)musics;

/**
 *  返回正在播放的歌曲
 */
+ (YYMusicModel *)playingMusic;
+ (void)setPlayingMusic:(YYMusicModel *)playingMusic;

/**
 *  下一首歌曲
 */
+ (YYMusicModel *)nextMusic;

/**
 *  上一首歌曲
 */
+ (YYMusicModel *)previousMusic;
@end

YYMusicTool.m文件
代码如下:


//
//  YYMusicTool.m
//

#import "YYMusicTool.h"
#import "YYMusicModel.h"
#import "MJExtension.h"

@implementation YYMusicTool

static NSArray *_musics;
static  YYMusicModel *_playingMusic;

/**
 *  @return 返回所有的歌曲
 */
+(NSArray *)musics
{
    if (_musics==nil) {
        _musics=[YYMusicModel objectArrayWithFilename:@"Musics.plist"];
    }
    return _musics;
}

+(void)setPlayingMusic:(YYMusicModel *)playingMusic
{
    /*
     *如果没有传入需要播放的歌曲,或者是传入的歌曲名不在音乐库中,那么就直接返回
      如果需要播放的歌曲就是当前正在播放的歌曲,那么直接返回
     */
    if (!playingMusic || ![[self musics]containsObject:playingMusic]) return;
    if (_playingMusic == playingMusic) return;
    _playingMusic=playingMusic;
}
/**
 *  返回正在播放的歌曲
 */
+(YYMusicModel *)playingMusic
{
    return _playingMusic;
}

/**
 *  下一首歌曲
 */
+(YYMusicModel *)nextMusic
{
    //设定一个初值
    int nextIndex = 0;
    if (_playingMusic) {
        //获取当前播放音乐的索引
        int playingIndex = [[self musics] indexOfObject:_playingMusic];
        //设置下一首音乐的索引
        nextIndex = playingIndex+1;
        //检查数组越界,如果下一首音乐是最后一首,那么重置为0
        if (nextIndex>=[self musics].count) {
            nextIndex=0;
        }
    }
    return [self musics][nextIndex];
}

/**
 *  上一首歌曲
 */
+(YYMusicModel *)previousMusic
{
    //设定一个初值
    int previousIndex = 0;
    if (_playingMusic) {
        //获取当前播放音乐的索引
        int playingIndex = [[self musics] indexOfObject:_playingMusic];
        //设置下一首音乐的索引
        previousIndex = playingIndex-1;
        //检查数组越界,如果下一首音乐是最后一首,那么重置为0
        if (previousIndex<0) {
            previousIndex=[self musics].count-1;
        }
    }
    return [self musics][previousIndex];
}
@end

三、封装一个音乐播放工具类

该工具类中的代码设计如下:

YYAudioTool.h文件
代码如下:

//
//  YYAudioTool.h
//

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
@interface YYAudioTool : NSObject
/**
 *播放音乐文件
 */
+(BOOL)playMusic:(NSString *)filename;
/**
 *暂停播放
 */
+(void)pauseMusic:(NSString *)filename;
/**
 *播放音乐文件
 */
+(void)stopMusic:(NSString *)filename;

/**
 *播放音效文件
 */
+(void)playSound:(NSString *)filename;
/**
 *销毁音效
 */
+(void)disposeSound:(NSString *)filename;
@end

YYAudioTool.m文件
代码如下:

//
//  YYAudioTool.m
//

#import "YYAudioTool.h"

@implementation YYAudioTool
/**
 *存放所有的音乐播放器
 */
static NSMutableDictionary *_musicPlayers;
+(NSMutableDictionary *)musicPlayers
{
    if (_musicPlayers==nil) {
        _musicPlayers=[NSMutableDictionary dictionary];
    }
    return _musicPlayers;
}

/**
 *存放所有的音效ID
 */
static NSMutableDictionary *_soundIDs;
+(NSMutableDictionary *)soundIDs
{
    if (_soundIDs==nil) {
        _soundIDs=[NSMutableDictionary dictionary];
    }
    return _soundIDs;
}


/**
 *播放音乐
 */
+(BOOL)playMusic:(NSString *)filename
{
    if (!filename) return NO;//如果没有传入文件名,那么直接返回
    //1.取出对应的播放器
    AVAudioPlayer *player=[self musicPlayers][filename];
   
    //2.如果播放器没有创建,那么就进行初始化
    if (!player) {
        //2.1音频文件的URL
        NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil];
        if (!url) return NO;//如果url为空,那么直接返回
       
        //2.2创建播放器
        player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
       
        //2.3缓冲
        if (![player prepareToPlay]) return NO;//如果缓冲失败,那么就直接返回
       
        //2.4存入字典
        [self musicPlayers][filename]=player;
    }
   
    //3.播放
    if (![player isPlaying]) {
        //如果当前没处于播放状态,那么就播放
        return [player play];
    }

    return YES;//正在播放,那么就返回YES
}

+(void)pauseMusic:(NSString *)filename
{
    if (!filename) return;//如果没有传入文件名,那么就直接返回
   
    //1.取出对应的播放器
    AVAudioPlayer *player=[self musicPlayers][filename];
   
    //2.暂停
    [player pause];//如果palyer为空,那相当于[nil pause],因此这里可以不用做处理

}

+(void)stopMusic:(NSString *)filename
{
    if (!filename) return;//如果没有传入文件名,那么就直接返回
   
    //1.取出对应的播放器
    AVAudioPlayer *player=[self musicPlayers][filename];
   
    //2.停止
    [player stop];
   
    //3.将播放器从字典中移除
    [[self musicPlayers] removeObjectForKey:filename];
}

//播放音效
+(void)playSound:(NSString *)filename
{
    if (!filename) return;
    //1.取出对应的音效
    SystemSoundID soundID=[[self soundIDs][filename] unsignedIntegerValue];
   
    //2.播放音效
    //2.1如果音效ID不存在,那么就创建
    if (!soundID) {
       
        //音效文件的URL
        NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil];
        if (!url) return;//如果URL不存在,那么就直接返回
       
        OSStatus status = AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url), &soundID);
        NSLog(@"%ld",status);
        //存入到字典中
        [self soundIDs][filename]=@(soundID);
    }
   
    //2.2有音效ID后,播放音效
    AudioServicesPlaySystemSound(soundID);
}

//销毁音效
+(void)disposeSound:(NSString *)filename
{
    //如果传入的文件名为空,那么就直接返回
    if (!filename) return;
   
    //1.取出对应的音效
    SystemSoundID soundID=[[self soundIDs][filename] unsignedIntegerValue];
   
    //2.销毁
    if (soundID) {
        AudioServicesDisposeSystemSoundID(soundID);
       
        //2.1销毁后,从字典中移除
        [[self soundIDs]removeObjectForKey:filename];
    }
}
@end

四、在音乐播放控制器中的代码处理

YYPlayingViewController.m文件
代码如下:


//
//  YYPlayingViewController.m
//

#import "YYPlayingViewController.h"
#import "YYMusicTool.h"
#import "YYMusicModel.h"
#import "YYAudioTool.h"

@interface YYPlayingViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *songLabel;
@property (weak, nonatomic) IBOutlet UILabel *singerLabel;
@property (weak, nonatomic) IBOutlet UILabel *durationLabel;
@property(nonatomic,strong)YYMusicModel *playingMusic;
- (IBAction)exit;

@end

代码如下:

@implementation YYPlayingViewController
#pragma mark-公共方法
-(void)show
{
    //1.禁用整个app的点击事件
    UIWindow *window=[UIApplication sharedApplication].keyWindow;
    window.userInteractionEnabled=NO;
   
    //2.添加播放界面
    //设置View的大小为覆盖整个窗口
    self.view.frame=window.bounds;
    //设置view显示
    self.view.hidden=NO;
    //把View添加到窗口上
    [window addSubview:self.view];
   
    //3.检测是否换了歌曲
    if (self.playingMusic!=[YYMusicTool playingMusic]) {
        [self RresetPlayingMusic];
    }
   
    //4.使用动画让View显示
    self.view.y=self.view.height;
    [UIView animateWithDuration:0.25 animations:^{
        self.view.y=0;
    } completion:^(BOOL finished) {
       
        //设置音乐数据
        [self starPlayingMusic];
        window.userInteractionEnabled=YES;
    }];
}
#pragma mark-私有方法
//重置正在播放的音乐
-(void)RresetPlayingMusic
{
    //1.重置界面数据
    self.iconView.image=[UIImage imageNamed:@"play_cover_pic_bg"];
    self.songLabel.text=nil;
    self.singerLabel.text=nil;
   
    //2.停止播放
    [YYAudioTool stopMusic:self.playingMusic.filename];
}
//开始播放音乐数据
-(void)starPlayingMusic
{
    //1.设置界面数据
   
    //取出当前正在播放的音乐
//    YYMusicModel *playingMusic=[YYMusicTool playingMusic];
   
    //如果当前播放的音乐就是传入的音乐,那么就直接返回
    if (self.playingMusic==[YYMusicTool playingMusic]) return;
    //存取音乐
    self.playingMusic=[YYMusicTool playingMusic];
    self.iconView.image=[UIImage imageNamed:self.playingMusic.icon];
    self.songLabel.text=self.playingMusic.name;
    self.singerLabel.text=self.playingMusic.singer;
   
    //2.开始播放
    [YYAudioTool playMusic:self.playingMusic.filename];
   
}

#pragma mark-内部的按钮监听方法
//返回按钮
- (IBAction)exit {
    //1.禁用整个app的点击事件
    UIWindow *window=[UIApplication sharedApplication].keyWindow;
    window.userInteractionEnabled=NO;
   
    //2.动画隐藏View
    [UIView animateWithDuration:0.25 animations:^{
        self.view.y=window.height;
    } completion:^(BOOL finished) {
        window.userInteractionEnabled=YES;
        //设置view隐藏能够节省一些性能
        self.view.hidden=YES;
    }];
}
@end

注意:先让用户看到界面上的所有东西后,再开始播放歌曲。

提示:一般的播放器需要做一个重置的操作。
  当从一首歌切换到另外一首时,应该先把上一首的信息删除,因此在show动画显示之前,应该检测是否换了歌曲,如果换了歌曲,则应该做一次重置操作。
实现效果(能够顺利的切换和播放歌曲,下面是界面显示):

iOS开发中音频工具类的封装以及音乐播放器的细节控制
iOS开发中音频工具类的封装以及音乐播放器的细节控制

五、补充代码

YYMusicsViewController.m文件
代码如下:


//
//  YYMusicsViewController.m
//

#import "YYMusicsViewController.h"
#import "YYMusicModel.h"
#import "MJExtension.h"
#import "YYMusicCell.h"
#import "YYPlayingViewController.h"
#import "YYMusicTool.h"

@interface YYMusicsViewController ()

@property(nonatomic,strong)YYPlayingViewController *playingViewController;
@end

代码如下:

@implementation YYMusicsViewController
#pragma mark-懒加载

-(YYPlayingViewController *)playingViewController
{
    if (_playingViewController==nil) {
        _playingViewController=[[YYPlayingViewController alloc]init];
    }
    return _playingViewController;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

#pragma mark - Table view data source
/**
 *一共多少组
 */
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}
/**
 *每组多少行
 */
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [YYMusicTool musics].count;
}
/**
 *每组每行的cell
 */
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    YYMusicCell *cell=[YYMusicCell cellWithTableView:tableView];
    cell.music=[YYMusicTool musics][indexPath.row];
    return cell;
}
/**
 *  设置每个cell的高度
 */
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 70;
}

/**
 *  cell的点击事件
 */
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //1.取消选中被点击的这行
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
   
    //2.设置正在播放的歌曲
    [YYMusicTool setPlayingMusic:[YYMusicTool musics][indexPath.row]];

    //调用公共方法
    [self.playingViewController show];
   
//    //执行segue跳转
//    [self performSegueWithIdentifier:@"music2playing" sender:nil];
}
@end

六、一些细节控制

再来看一个实现的效果:

iOS开发中音频工具类的封装以及音乐播放器的细节控制

完整的代码

YYPlayingViewController.m文件
代码如下:


//
//  YYPlayingViewController.m
//  20-音频处理(音乐播放器1)
//
//  Created by apple on 14-8-13.
//  Copyright (c) 2014年 yangyong. All rights reserved.
//

#import "YYPlayingViewController.h"
#import "YYMusicTool.h"
#import "YYMusicModel.h"
#import "YYAudioTool.h"

@interface YYPlayingViewController ()
//进度条
@property (weak, nonatomic) IBOutlet UIView *progressView;
//滑块
@property (weak, nonatomic) IBOutlet UIButton *slider;
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *songLabel;
@property (weak, nonatomic) IBOutlet UILabel *singerLabel;
//当前播放的音乐的时长
@property (weak, nonatomic) IBOutlet UILabel *durationLabel;
//正在播放的音乐
@property(nonatomic,strong)YYMusicModel *playingMusic;
//音乐播放器对象
@property(nonatomic,strong)AVAudioPlayer *player;
//定时器
@property(nonatomic,strong)NSTimer *CurrentTimeTimer;
- (IBAction)exit;
- (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender;
- (IBAction)panSlider:(UIPanGestureRecognizer *)sender;

@end

代码如下:


@implementation YYPlayingViewController
#pragma mark-公共方法
-(void)show
{
    //1.禁用整个app的点击事件
    UIWindow *window=[UIApplication sharedApplication].keyWindow;
    window.userInteractionEnabled=NO;
   
    //2.添加播放界面
    //设置View的大小为覆盖整个窗口
    self.view.frame=window.bounds;
    //设置view显示
    self.view.hidden=NO;
    //把View添加到窗口上
    [window addSubview:self.view];
   
    //3.检测是否换了歌曲
    if (self.playingMusic!=[YYMusicTool playingMusic]) {
        [self RresetPlayingMusic];
    }
   
    //4.使用动画让View显示
    self.view.y=self.view.height;
    [UIView animateWithDuration:0.25 animations:^{
        self.view.y=0;
    } completion:^(BOOL finished) {
       
        //设置音乐数据
        [self starPlayingMusic];
        window.userInteractionEnabled=YES;
    }];
}


#pragma mark-私有方法
//重置正在播放的音乐
-(void)RresetPlayingMusic
{
    //1.重置界面数据
    self.iconView.image=[UIImage imageNamed:@"play_cover_pic_bg"];
    self.songLabel.text=nil;
    self.singerLabel.text=nil;
   
    //2.停止播放
    [YYAudioTool stopMusic:self.playingMusic.filename];
    //把播放器进行清空
    self.player=nil;
   
    //3.停止定时器
    [self removeCurrentTime];
}
//开始播放音乐数据
-(void)starPlayingMusic
{
    //1.设置界面数据
   
    //如果当前播放的音乐就是传入的音乐,那么就直接返回
    if (self.playingMusic==[YYMusicTool playingMusic])
    {
        //把定时器加进去
        [self addCurrentTimeTimer];
        return;
    }
    //存取音乐
    self.playingMusic=[YYMusicTool playingMusic];
    self.iconView.image=[UIImage imageNamed:self.playingMusic.icon];
    self.songLabel.text=self.playingMusic.name;
    self.singerLabel.text=self.playingMusic.singer;
   
    //2.开始播放
    self.player = [YYAudioTool playMusic:self.playingMusic.filename];
   
    //3.设置时长
    //self.player.duration;  播放器正在播放的音乐文件的时间长度
    self.durationLabel.text=[self strWithTime:self.player.duration];
   
    //4.添加定时器
    [self addCurrentTimeTimer];
   
}

/**
 *把时间长度-->时间字符串
 */
-(NSString *)strWithTime:(NSTimeInterval)time
{
    int minute=time / 60;
    int second=(int)time % 60;
    return [NSString stringWithFormat:@"%d:%d",minute,second];
}

#pragma mark-定时器控制
/**
 *  添加一个定时器
 */
-(void)addCurrentTimeTimer
{
    //提前先调用一次进度更新,以保证定时器的工作时及时的
    [self updateCurrentTime];
   
    //创建一个定时器,每一秒钟调用一次
    self.CurrentTimeTimer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCurrentTime) userInfo:nil repeats:YES];
    //把定时器加入到运行时中
    [[NSRunLoop mainRunLoop]addTimer:self.CurrentTimeTimer forMode:NSRunLoopCommonModes];
}
/**
 *移除一个定时器
 */
-(void)removeCurrentTime
{
    [self.CurrentTimeTimer invalidate];
   
    //把定时器清空
    self.CurrentTimeTimer=nil;
}

/**
 *  更新播放进度
 */
-(void)updateCurrentTime
{
    //1.计算进度值
    double progress=self.player.currentTime/self.player.duration;
   
    //2.计算滑块的x值
    // 滑块的最大的x值
    CGFloat sliderMaxX=self.view.width-self.slider.width;
    self.slider.x=sliderMaxX*progress;
    //设置滑块上的当前播放时间
    [self.slider setTitle:[self strWithTime:self.player.currentTime] forState:UIControlStateNormal];
   
    //3.设置进度条的宽度
    self.progressView.width=self.slider.center.x;
   
}

#pragma mark-内部的按钮监听方法
//返回按钮
- (IBAction)exit {
   
    //0.移除定时器
    [self  removeCurrentTime];
    //1.禁用整个app的点击事件
    UIWindow *window=[UIApplication sharedApplication].keyWindow;
    window.userInteractionEnabled=NO;
   
    //2.动画隐藏View
    [UIView animateWithDuration:0.25 animations:^{
        self.view.y=window.height;
    } completion:^(BOOL finished) {
        window.userInteractionEnabled=YES;
        //设置view隐藏能够节省一些性能
        self.view.hidden=YES;
    }];
}

/**
 *点击了进度条
 */
- (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender {
    //获取当前单击的点
    CGPoint point=[sender locationInView:sender.view];
    //切换歌曲的当前播放时间
    self.player.currentTime=(point.x/sender.view.width)*self.player.duration;
    //更新播放进度
    [self updateCurrentTime];
}

- (IBAction)panSlider:(UIPanGestureRecognizer *)sender {
   
    //1.获得挪动的距离
    CGPoint t=[sender translationInView:sender.view];
    //把挪动清零
    [sender setTranslation:CGPointZero inView:sender.view];
   
    //2.控制滑块和进度条的frame
    self.slider.x+=t.x;
    //设置进度条的宽度
    self.progressView.width=self.slider.center.x;
   
    //3.设置时间值
    CGFloat sliderMaxX=self.view.width-self.slider.width;
    double progress=self.slider.x/sliderMaxX;
    //当前的时间值=音乐的时长*当前的进度值
    NSTimeInterval time=self.player.duration*progress;
    [self .slider setTitle:[self strWithTime:time] forState:UIControlStateNormal];
   
    //4.如果开始拖动,那么就停止定时器
    if (sender.state==UIGestureRecognizerStateBegan) {
        //停止定时器
        [self removeCurrentTime];
    }else if(sender.state==UIGestureRecognizerStateEnded)
    {
        //设置播放器播放的时间
        self.player.currentTime=time;
        //开启定时器
        [self addCurrentTimeTimer];
    }
}
@end

代码说明(一)

调整开始播放音乐按钮,让其返回一个音乐播放器,而非BOOL型的。
代码如下:


/**
 *播放音乐
 */
+(AVAudioPlayer *)playMusic:(NSString *)filename
{
    if (!filename) return nil;//如果没有传入文件名,那么直接返回
    //1.取出对应的播放器
    AVAudioPlayer *player=[self musicPlayers][filename];
   
    //2.如果播放器没有创建,那么就进行初始化
    if (!player) {
        //2.1音频文件的URL
        NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil];
        if (!url) return nil;//如果url为空,那么直接返回
       
        //2.2创建播放器
        player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
       
        //2.3缓冲
        if (![player prepareToPlay]) return nil;//如果缓冲失败,那么就直接返回
       
        //2.4存入字典
        [self musicPlayers][filename]=player;
    }
   
    //3.播放
    if (![player isPlaying]) {
        //如果当前没处于播放状态,那么就播放
         [player play];
    }

    return player;//正在播放,那么就返回YES
}

代码说明(二)

把时间转换为时间字符串的方法:
代码如下:


/**
 *把时间长度-->时间字符串
 */
-(NSString *)strWithTime:(NSTimeInterval)time
{
    int minute=time / 60;
    int second=(int)time % 60;
    return [NSString stringWithFormat:@"%d:%d",minute,second];
}

代码说明(三)

说明:进度控制

监听当前的播放,使用一个定时器,不断的监听当前是第几秒。

关于定时器的处理:这里使用了三个方法,分别是添加定时器,移除定时器,和更新播放进度。

注意细节:

(1)移除定时器后,对定时器进行清空处理。
代码如下:


/**
 *移除一个定时器
 */
-(void)removeCurrentTime
{
    [self.CurrentTimeTimer invalidate];
   
    //把定时器清空
    self.CurrentTimeTimer=nil;
}

(2)当看不到界面的时候,停止定时器。

(3)在开始播放音乐的方法中进行判断,如果当前播放的音乐和传入的音乐一致,那么添加定时器后直接返回。

(4)重置播放的音乐方法中,停止定时器。

代码说明(四)

说明:点击和拖动进度条的处理

(1)点击进度条

先添加单击的手势识别器。

iOS开发中音频工具类的封装以及音乐播放器的细节控制

往控制器拖线:

iOS开发中音频工具类的封装以及音乐播放器的细节控制

涉及的代码:
代码如下:


/**
 *点击了进度条
 */
- (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender {
    //获取当前单击的点
    CGPoint point=[sender locationInView:sender.view];
    //切换歌曲的当前播放时间
    self.player.currentTime=(point.x/sender.view.width)*self.player.duration;
    //更新播放进度
    [self updateCurrentTime];
}

(2)拖拽进度条

先添加拖拽手势识别器

iOS开发中音频工具类的封装以及音乐播放器的细节控制

往控制器拖线

iOS开发中音频工具类的封装以及音乐播放器的细节控制

涉及的代码:
代码如下:


/**
 *拖动滑块
 */
- (IBAction)panSlider:(UIPanGestureRecognizer *)sender {
   
    //1.获得挪动的距离
    CGPoint t=[sender translationInView:sender.view];
    //把挪动清零
    [sender setTranslation:CGPointZero inView:sender.view];
   
    //2.控制滑块和进度条的frame
    self.slider.x+=t.x;
    //设置进度条的宽度
    self.progressView.width=self.slider.center.x;
   
    //3.设置时间值
    CGFloat sliderMaxX=self.view.width-self.slider.width;
    double progress=self.slider.x/sliderMaxX;
    //当前的时间值=音乐的时长*当前的进度值
    NSTimeInterval time=self.player.duration*progress;
    [self .slider setTitle:[self strWithTime:time] forState:UIControlStateNormal];
   
    //4.如果开始拖动,那么就停止定时器
    if (sender.state==UIGestureRecognizerStateBegan) {
        //停止定时器
        [self removeCurrentTime];
    }else if(sender.state==UIGestureRecognizerStateEnded)
    {
        //设置播放器播放的时间
        self.player.currentTime=time;
        //开启定时器
        [self addCurrentTimeTimer];
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容