iOS开发拓展篇—音频处理(音乐播放器4)

简介:

说明:该文主要介绍音乐播放器实现过程中的一些细节控制。

实现的效果:

一、完整的代码

YYPlayingViewController.m文件

复制代码
 1 //  2 // YYPlayingViewController.m
 3 // 20-音频处理(音乐播放器1)
 4 //  5 // Created by apple on 14-8-13.
 6 // Copyright (c) 2014年 yangyong. All rights reserved.
 7 //
 8  9 #import "YYPlayingViewController.h"  10 #import "YYMusicTool.h"  11 #import "YYMusicModel.h"  12 #import "YYAudioTool.h"  13  14 @interface YYPlayingViewController ()
 15 //进度条  16 @property (weak, nonatomic) IBOutlet UIView *progressView;
 17 //滑块  18 @property (weak, nonatomic) IBOutlet UIButton *slider;
 19 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
 20 @property (weak, nonatomic) IBOutlet UILabel *songLabel;
 21 @property (weak, nonatomic) IBOutlet UILabel *singerLabel;
 22 //当前播放的音乐的时长  23 @property (weak, nonatomic) IBOutlet UILabel *durationLabel;
 24 //正在播放的音乐  25 @property(nonatomic,strong)YYMusicModel *playingMusic;
 26 //音乐播放器对象  27 @property(nonatomic,strong)AVAudioPlayer *player;
 28 //定时器  29 @property(nonatomic,strong)NSTimer *CurrentTimeTimer;
 30 - (IBAction)exit;
 31 - (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender;
 32 - (IBAction)panSlider:(UIPanGestureRecognizer *)sender;
 33  34 @end  35  36 @implementation YYPlayingViewController
 37 #pragma mark-公共方法
 38 -(void)show
 39 {
 40 //1.禁用整个app的点击事件  41 UIWindow *window=[UIApplication sharedApplication].keyWindow;
 42 window.userInteractionEnabled=NO;
 43  44 //2.添加播放界面
 45 //设置View的大小为覆盖整个窗口  46 self.view.frame=window.bounds;
 47 //设置view显示  48 self.view.hidden=NO;
 49 //把View添加到窗口上  50  [window addSubview:self.view];
 51  52 //3.检测是否换了歌曲  53 if (self.playingMusic!=[YYMusicTool playingMusic]) {
 54  [self RresetPlayingMusic];
 55  }
 56  57 //4.使用动画让View显示  58 self.view.y=self.view.height;
 59 [UIView animateWithDuration:0.25 animations:^{
 60 self.view.y=0;
 61 } completion:^(BOOL finished) {
 62  63 //设置音乐数据  64  [self starPlayingMusic];
 65 window.userInteractionEnabled=YES;
 66  }];
 67 }
 68  69  70 #pragma mark-私有方法
 71 //重置正在播放的音乐  72 -(void)RresetPlayingMusic
 73 {
 74 //1.重置界面数据  75 self.iconView.image=[UIImage imageNamed:@"play_cover_pic_bg"];
 76 self.songLabel.text=nil;
 77 self.singerLabel.text=nil;
 78  79 //2.停止播放  80  [YYAudioTool stopMusic:self.playingMusic.filename];
 81 //把播放器进行清空  82 self.player=nil;
 83  84 //3.停止定时器  85  [self removeCurrentTime];
 86 }
 87 //开始播放音乐数据  88 -(void)starPlayingMusic
 89 {
 90 //1.设置界面数据
 91  92 //如果当前播放的音乐就是传入的音乐,那么就直接返回  93 if (self.playingMusic==[YYMusicTool playingMusic])
 94  {
 95 //把定时器加进去  96  [self addCurrentTimeTimer];
 97 return;
 98  }
 99 //存取音乐 100 self.playingMusic=[YYMusicTool playingMusic];
101 self.iconView.image=[UIImage imageNamed:self.playingMusic.icon];
102 self.songLabel.text=self.playingMusic.name;
103 self.singerLabel.text=self.playingMusic.singer;
104 105 //2.开始播放 106 self.player = [YYAudioTool playMusic:self.playingMusic.filename];
107 108 //3.设置时长
109 //self.player.duration; 播放器正在播放的音乐文件的时间长度 110 self.durationLabel.text=[self strWithTime:self.player.duration];
111 112 //4.添加定时器 113  [self addCurrentTimeTimer];
114 115 }
116 117 /**
118  *把时间长度-->时间字符串
119 */ 120 -(NSString *)strWithTime:(NSTimeInterval)time
121 {
122 int minute=time / 60;
123 int second=(int)time % 60;
124 return [NSString stringWithFormat:@"%d:%d",minute,second];
125 }
126 127 #pragma mark-定时器控制
128 /**
129  * 添加一个定时器
130 */ 131 -(void)addCurrentTimeTimer
132 {
133 //提前先调用一次进度更新,以保证定时器的工作时及时的 134  [self updateCurrentTime];
135 136 //创建一个定时器,每一秒钟调用一次 137 self.CurrentTimeTimer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCurrentTime) userInfo:nil repeats:YES];
138 //把定时器加入到运行时中 139  [[NSRunLoop mainRunLoop]addTimer:self.CurrentTimeTimer forMode:NSRunLoopCommonModes];
140 }
141 /**
142  *移除一个定时器
143 */ 144 -(void)removeCurrentTime
145 {
146  [self.CurrentTimeTimer invalidate];
147 148 //把定时器清空 149 self.CurrentTimeTimer=nil;
150 }
151 152 /**
153  * 更新播放进度
154 */ 155 -(void)updateCurrentTime
156 {
157 //1.计算进度值 158 double progress=self.player.currentTime/self.player.duration;
159 160 //2.计算滑块的x值
161 // 滑块的最大的x值 162 CGFloat sliderMaxX=self.view.width-self.slider.width;
163 self.slider.x=sliderMaxX*progress;
164 //设置滑块上的当前播放时间 165  [self.slider setTitle:[self strWithTime:self.player.currentTime] forState:UIControlStateNormal];
166 167 //3.设置进度条的宽度 168 self.progressView.width=self.slider.center.x;
169 170 }
171 172 #pragma mark-内部的按钮监听方法
173 //返回按钮 174 - (IBAction)exit {
175 176 //0.移除定时器 177  [self removeCurrentTime];
178 //1.禁用整个app的点击事件 179 UIWindow *window=[UIApplication sharedApplication].keyWindow;
180 window.userInteractionEnabled=NO;
181 182 //2.动画隐藏View 183 [UIView animateWithDuration:0.25 animations:^{
184 self.view.y=window.height;
185 } completion:^(BOOL finished) {
186 window.userInteractionEnabled=YES;
187 //设置view隐藏能够节省一些性能 188 self.view.hidden=YES;
189  }];
190 }
191 192 /**
193  *点击了进度条
194 */ 195 - (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender {
196 //获取当前单击的点 197 CGPoint point=[sender locationInView:sender.view];
198 //切换歌曲的当前播放时间 199 self.player.currentTime=(point.x/sender.view.width)*self.player.duration;
200 //更新播放进度 201  [self updateCurrentTime];
202 }
203 204 - (IBAction)panSlider:(UIPanGestureRecognizer *)sender {
205 206 //1.获得挪动的距离 207 CGPoint t=[sender translationInView:sender.view];
208 //把挪动清零 209  [sender setTranslation:CGPointZero inView:sender.view];
210 211 //2.控制滑块和进度条的frame 212 self.slider.x+=t.x;
213 //设置进度条的宽度 214 self.progressView.width=self.slider.center.x;
215 216 //3.设置时间值 217 CGFloat sliderMaxX=self.view.width-self.slider.width;
218 double progress=self.slider.x/sliderMaxX;
219 //当前的时间值=音乐的时长*当前的进度值 220 NSTimeInterval time=self.player.duration*progress;
221  [self .slider setTitle:[self strWithTime:time] forState:UIControlStateNormal];
222 223 //4.如果开始拖动,那么就停止定时器 224 if (sender.state==UIGestureRecognizerStateBegan) {
225 //停止定时器 226  [self removeCurrentTime];
227 }else if(sender.state==UIGestureRecognizerStateEnded)
228  {
229 //设置播放器播放的时间 230 self.player.currentTime=time;
231 //开启定时器 232  [self addCurrentTimeTimer];
233  }
234 }
235 @end
复制代码

二、代码说明(一)

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

复制代码
 1 /**
 2  *播放音乐
 3 */  4 +(AVAudioPlayer *)playMusic:(NSString *)filename
 5 {
 6 if (!filename) return nil;//如果没有传入文件名,那么直接返回
 7 //1.取出对应的播放器  8 AVAudioPlayer *player=[self musicPlayers][filename];
 9 10 //2.如果播放器没有创建,那么就进行初始化 11 if (!player) {
12 //2.1音频文件的URL 13 NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil];
14 if (!url) return nil;//如果url为空,那么直接返回
15 16 //2.2创建播放器 17 player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
18 19 //2.3缓冲 20 if (![player prepareToPlay]) return nil;//如果缓冲失败,那么就直接返回
21 22 //2.4存入字典 23 [self musicPlayers][filename]=player;
24  }
25 26 //3.播放 27 if (![player isPlaying]) {
28 //如果当前没处于播放状态,那么就播放 29  [player play];
30  }
31 32 return player;//正在播放,那么就返回YES 33 }
复制代码

三、代码说明(二)

  把时间转换为时间字符串的方法:

复制代码
1 /**
2  *把时间长度-->时间字符串
3 */ 4 -(NSString *)strWithTime:(NSTimeInterval)time
5 {
6 int minute=time / 60;
7 int second=(int)time % 60;
8 return [NSString stringWithFormat:@"%d:%d",minute,second];
9 }
复制代码

四、代码说明(三)

  说明:进度控制

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

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

注意细节:

(1)移除定时器后,对定时器进行清空处理。

复制代码
 1 /**
 2  *移除一个定时器
 3 */  4 -(void)removeCurrentTime
 5 {
 6  [self.CurrentTimeTimer invalidate];
 7  8 //把定时器清空  9 self.CurrentTimeTimer=nil;
10 }
复制代码

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

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

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

五、代码说明(四)

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

1.点击进度条

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

  往控制器拖线:

涉及的代码:

复制代码
 1 /**
 2  *点击了进度条
 3 */  4 - (IBAction)tapProgressBg:(UITapGestureRecognizer *)sender {
 5 //获取当前单击的点  6 CGPoint point=[sender locationInView:sender.view];
 7 //切换歌曲的当前播放时间  8 self.player.currentTime=(point.x/sender.view.width)*self.player.duration;
 9 //更新播放进度 10  [self updateCurrentTime];
11 }
复制代码

2.拖拽进度条

  先添加拖拽手势识别器

往控制器拖线

涉及的代码:

复制代码
 1 /**
 2  *拖动滑块
 3 */  4 - (IBAction)panSlider:(UIPanGestureRecognizer *)sender {
 5  6 //1.获得挪动的距离  7 CGPoint t=[sender translationInView:sender.view];
 8 //把挪动清零  9  [sender setTranslation:CGPointZero inView:sender.view];
10 11 //2.控制滑块和进度条的frame 12 self.slider.x+=t.x;
13 //设置进度条的宽度 14 self.progressView.width=self.slider.center.x;
15 16 //3.设置时间值 17 CGFloat sliderMaxX=self.view.width-self.slider.width;
18 double progress=self.slider.x/sliderMaxX;
19 //当前的时间值=音乐的时长*当前的进度值 20 NSTimeInterval time=self.player.duration*progress;
21  [self .slider setTitle:[self strWithTime:time] forState:UIControlStateNormal];
22 23 //4.如果开始拖动,那么就停止定时器 24 if (sender.state==UIGestureRecognizerStateBegan) {
25 //停止定时器 26  [self removeCurrentTime];
27 }else if(sender.state==UIGestureRecognizerStateEnded)
28  {
29 //设置播放器播放的时间 30 self.player.currentTime=time;
31 //开启定时器 32  [self addCurrentTimeTimer];
33  }
34 }
复制代码
目录
相关文章
|
2月前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
106 3
|
2月前
|
API 开发工具 Android开发
iOS 和 Android 平台的开发有哪些主要区别?
iOS与Android开发区别:iOS用Objective-C/Swift,App Store唯一下载渠道;Android用Java/Kotlin,多商店发布(如Google Play、华为市场)。设计上,iOS简洁一致,Android灵活可定制。开发工具,iOS用Xcode,Android用Android Studio。硬件和系统多样性,iOS统一,Android复杂。权限管理、审核流程及API各有特点,开发者需依据目标平台特性进行选择。
36 3
|
11天前
|
前端开发 Android开发 iOS开发
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
【4月更文挑战第30天】Flutter 框架实现跨平台移动应用,通过一致的 UI 渲染(Skia 引擎)、热重载功能和响应式框架提高开发效率和用户体验。然而,Android 和 iOS 的系统差异、渲染机制及编译过程影响性能。性能对比显示,iOS 可能因硬件优化提供更流畅体验,而 Android 更具灵活性和广泛硬件支持。开发者可采用代码、资源优化和特定平台优化策略,利用性能分析工具提升应用性能。
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
|
11天前
|
存储 Swift iOS开发
使用Swift开发一个简单的iOS应用的详细步骤。
使用Swift开发iOS应用的步骤包括:创建Xcode项目,设计界面(Storyboard或代码),定义数据模型,实现业务逻辑,连接界面和逻辑,处理数据存储(如Core Data),添加网络请求(必要时),调试与测试,根据测试结果优化改进,最后提交至App Store或其它平台发布。
32 0
|
12天前
|
安全 Swift iOS开发
【Swift 开发专栏】Swift 与 UIKit:构建 iOS 应用界面
【4月更文挑战第30天】本文探讨了Swift和UIKit在构建iOS应用界面的关键技术和实践方法。Swift的简洁语法、类型安全和高效编程模型,加上与UIKit的紧密集成,使开发者能便捷地创建用户界面。UIKit提供视图、控制器、布局、动画和事件处理等功能,支持灵活的界面设计。实践中,遵循设计原则,合理组织视图层次,运用布局和动画,以及实现响应式设计,能提升界面质量和用户体验。文章通过登录、列表和详情界面的实际案例展示了Swift与UIKit的结合应用。
|
12天前
|
存储 安全 Swift
【Swift 开发专栏】使用 Swift 开发一个简单的 iOS 应用
【4月更文挑战第30天】本文介绍了使用 Swift 开发简单 iOS 待办事项应用的步骤。首先,阐述了 iOS 开发的吸引力及 Swift 语言的优势。接着,详细说明了应用的需求和设计,包括添加、查看和删除待办事项的功能。开发步骤包括创建项目、界面搭建、数据存储、功能实现,并提供了相关代码示例。最后,强调了实际开发中需注意的细节和优化,旨在帮助初学者掌握 Swift 和 iOS 开发基础。
|
20天前
|
iOS开发 开发者 UED
利用SwiftUI构建动态列表:iOS开发的新范式
【4月更文挑战第22天】在本文中,我们将深入探讨如何使用SwiftUI来创建动态列表。SwiftUI是苹果最新推出的用户界面工具集,它允许开发者以声明式的方式描述用户界面,从而简化了代码的复杂性。我们将通过具体的代码实例,展示如何利用SwiftUI的List和ForEach视图来创建动态列表,并讨论其在实际开发中的应用。
18 2
|
24天前
|
API 定位技术 iOS开发
IOS开发基础知识:什么是 Cocoa Touch?它在 iOS 开发中的作用是什么?
【4月更文挑战第18天】**Cocoa Touch** 是iOS和Mac OS X应用的核心框架,包含面向对象库、运行时系统和触摸优化工具。它提供Mac验证的开发模式,强调触控接口和性能,涵盖3D图形、音频、网络及设备访问API,如相机和GPS。是构建高效iOS应用的基础,对开发者至关重要。
21 0
|
1月前
|
搜索推荐 iOS开发 开发者
利用SwiftUI构建动态用户界面:iOS开发新篇章
【4月更文挑战第10天】在移动应用的世界中,流畅的用户体验和引人注目的界面设计是至关重要的。随着SwiftUI的推出,iOS开发者被赋予了创造高度动态且响应式界面的能力。本文将深入探讨如何利用SwiftUI的强大特性来实现一个动态用户界面,包括其声明性语法、状态绑定以及视图更新机制。我们将通过一个天气应用案例,了解如何有效地运用这些工具来提升应用的交互性和视觉吸引力。
|
1月前
|
开发工具 Swift iOS开发
利用SwiftUI构建动态用户界面:iOS开发新范式
【4月更文挑战第3天】 随着苹果不断推进其软件开发工具的边界,SwiftUI作为一种新兴的编程框架,已经逐渐成为iOS开发者的新宠。不同于传统的UIKit,SwiftUI通过声明式语法和强大的功能组合,为创建动态且响应式的用户界面提供了一种更加简洁高效的方式。本文将深入探讨如何利用SwiftUI技术构建具有高度自定义能力和响应性的用户界面,并展示其在现代iOS应用开发中的优势和潜力。