《iOS组件与框架——iOS SDK高级特性剖析》——第6章,第6.2节打造播放引擎

简介:

本节书摘来自异步社区《iOS组件与框架——iOS SDK高级特性剖析》一书中的第6章,第6.2节打造播放引擎,作者 【美】Kyle Richter , Joe Keeley,更多章节内容可以访问云栖社区“异步社区”公众号查看

6.2 打造播放引擎
iOS组件与框架——iOS SDK高级特性剖析
如果对播放控制没有深刻认识,获取音频数据将毫无意义。要在应用中播放音乐,需要创建一个MPMusicPlayerController实例。在头文件ICFViewController.h中,声明了一个名为player的MPMusicPlayerController变量,在整个示例应用中,都将使用它来控制播放以及获取当前播放的曲目的信息。


fec03b36e9c6b382bac747435540a385257e45ad

在方法viewDidLoad中,初始化了MPMusicPlayerController变量player,这是使用MPMusicPlayerController的一个类方法完成的。创建MPMusicPlayerController实例的方式有两种:一是使用applicationMusicPlayer,这将在应用内播放音乐,不影响iPod的状态,并在应用退出后停止播放;二是使用iPodMusicPlayer,这将控制应用iPod,从iPod播放头的位置开始继续播放,应用进入后台后也不会停止播放。本章的示例应用使用的是applicationMusicPlayer;但可轻松地转而使用iPodMusicPlayer,而无需对其他代码做任何修改。


e5eb713a5a6c936d5d3cb255fb913cbc9b09b706

6.2.1 注册播放通知
要有效地播放音乐,必须知道音乐播放器的状态。处理音乐播放器时,需要监视3种通知:当前播放的乐曲变了、音量变了,以及播放状态发生了变化。要监视这些状态,可使用NSNotificationCenter来订阅前述事件。为确保代码整洁易懂,示例应用使用了辅助方法registerMediaPlayerNotifications。将观察者加入NSNotificationCenter后,需要对对象player调用beginGeneratingPlaybackNotifications。


b8780d1c49617b927221b5e4a1d00d9ad5586e07

注册通知后,确保在清理内存和视图期间将它们注销,这很重要,否则将导致应用崩溃以及其他意外行为。另外,在方法viewWillDisapper中还调用了endGeneratingPlayback Notifications。


8981aa28cdbe57c46565b55a63c514e0655819a0

除注册音乐播放器回调方法外,还将创建一个NSTimer,用于更新播放进度和播放头时间标签。在示例应用中,这个NSTimer名为playbackTimer。对于通知回调方法和NSTimer,暂时就介绍这些,后面的6.2.3节将详细讨论它们。

6.2.2 播放控制
示例应用提供了多个让用户能够与音乐播放器交互的按钮,如播放、暂停、下一曲、前一曲以及前进和后退30秒。首先需要实现的是播放和暂停方法。这是一个简单的切换按钮:如果正在播放,就暂停;如果已暂停或停止,就继续播放。至于将按钮文本在Play和Pause之间切换的代码,将在6.2.3节讨论状态变化通知回调方法时进行讨论。


850b5a98dc42d80856abb0d0179720e0d92a9a8c

用户欣赏音乐时,还应能够跳到下一曲或前一曲。这是通过对对象player调用另外两个方法实现的。


0917772c92f5cd958bc079a3cda1db1bab8fb7fc


0b80e7afb0ce6b21ffc3da30070381535046d7eb

6.2.3 响应状态变化
前面给3个通知注册了回调方法。这些通知让应用能够获悉MPMusicPlayerController的当前状态和行为。当前播放的曲目变了时,将调用第一个方法。这个方法包含两部分,第一部分更新专辑封面,第二部分更新显示艺术家、曲目名和专辑的标签。

MPMusicPlayerController当前播放的音频或视频由一个MPMediaItem对象表示,要获取这个对象,可对MPMusicPlayerController实例调用方法nowPlayingItem。

创建了一个用于表示专辑封面的UIImage,并将其初始化为一个占位符,在MPMediaItem没有专辑封面时将显示该占位符。MPMediaItem使用键值属性来表示存储的数据,表6.1列出了所有的键值属性。创建了一个MPMediaItemArtwork,并将其设置为专辑封面数据。Apple文档指出,如果没有专辑封面,获取属性MPMediaItemPropertyArtwork时将返回nil,但实际情况并非如此。为解决这个问题,将专辑封面加载到一个UIImage中,并检查结果。如果结果为nil,就认为没有专辑封面,进而加载前面指定的占位符。即便MPMediaItemPropertyArtwork在没有专辑封面时返回nil,示例应用也能正常运行。


ce4c0a44aeb0dd8f67faf193ccfea7be54beb70b


f6d859ad4f2646d4f5b244f60f3ddca79c769f95

方法nowPlayingItemChanged:的第二部分更新歌曲名、艺术家信息和专辑名,如图6.1所示。如果获取这些属性时返回nil,就使用占位符字符串。表6.1列出了MPMediaItem的所有可访问属性。请注意,媒体项为播客时,则除表6.1所示的属性外,还有其他一些属性,详情请参阅Apple的MPMediaItem文档。在这个表中,还指出了以编程方式查找媒体项时,属性键是否可用于谓词搜索。

[


60ee882bc6bd25b55efbc0214dab8f655a78fd4f

监视音乐播放器的状态很重要,在状态可能受应用无法控制的外部输入的影响时尤其如此。如果状态发生变化,将调用方法playbackStateChanged:。在这个方法中,创建了变量playbackState,用于存储播放器的当前状态。这个方法执行了多项重要任务,其中第一项任务是更新按钮play/pause的文本,以反映当前状态。另外,创建和拆除了6.2.1节提到的NSTimer。如果应用正在播放音频,就将该定时器设置为每隔0.3秒触发一次,以便更新播放时间标签以及指出播放头位置的UIProgressIndicator。这个定时器触发的方法updateCurrentPlaybackTimer将在下一小节讨论。

除这个示例应用演示的状态外,还有其他3种状态。第一种状态是MPMusicPlaybackState Interrupted,表示音频播放中断,如来电导致中断。其他两种状态是MPMusicPlaybackState SeekingForward和MPMusicPlaybackStateSeekingBackward,表示音乐播放器正为查找指定播放位置而前进或后退。


2021c5e606565ac0433c621df9090636eb3fab24

如果音量发生变化,也必须通过应用的音量滑块反映出来。这是由通知回调方法volume Changed:完成的。在这个方法中,获取了播放器的当前音量,并相应地设置volumeSlider。


4f7028396bf1566d6d739e2d0b0a693adf25548f

6.2.4 时长和定时器
在大多数情况下,用户都想获悉当前播放的歌曲的信息,如已播放多长时间以及还有多长时间。示例应用包含两个显示这些数据的方法。第一个是updateSongDuration,在当前播放的歌曲变了或应用启动时被调用。它创建一个指向当前播放歌曲的引用,再使用属性键playbackDuration获取该歌曲的时长(单位为秒)。然后,将这项数据转换为小时、分钟和秒数,并将结果显示在UIProgressIndicator旁边的标签上。


a98a6fd4223322cabd8f0b6d70fe82731a672689

第二个方法是updateCurrentPlaybackTime,由NSTimer每隔0.3秒调用一次,而这个NSTimer由6.2.3节讨论的方法playbackStateChanged:控制。与方法updateSongDuration一样,将已播放的时间转换为小时、分钟和秒数;另外,还根据前面确定的歌曲时长计算percentagePlayed,并使用它来更新playbackProgressIndicator。由于currentPlaybackTime只能精确到秒,因此没有必要过于频繁地调用这个方法。然而,调用这个方法的频率越高,显示的结果就越精确。


d3f4025443bbc5af262dc0ed38f7c837420e9bf3

6.2.5 随机播放和重复播放
除前面提到的属性和控制外,还可指定MPMusicPlayerController的属性repeatMode和shuffleMode。虽然示例应用没有实现设置这两个属性的功能,但实现起来非常容易。


dcbb9a8582f4f6eac358d46e38548ce73bad362a

重复播放模式包括MPMusicRepeatModeDefault(用户的预定义首选模式)、MPMusicRepeat ModeNone、MPMusicRepeatModeOne和MPMusicRepeatModeAll。

随机播放模式包括MPMusicShuffleModeDefault(用户的预定义首选模式)、MPMusicShuffle ModeOff、MPMusicShuffleModeSongs和MPMusicShuffleModeAlbums,其中MPMusicShuffle ModeDefault表示用户的预定义首选模式。

相关文章
|
16天前
|
搜索推荐 数据管理 定位技术
iOS应用开发中有多种主流框架
iOS应用开发中有多种主流框架
137 60
|
16天前
|
iOS开发 开发者
探索iOS开发中的SwiftUI框架
【10月更文挑战第39天】在苹果的生态系统中,SwiftUI框架以其声明式语法和易用性成为开发者的新宠。本文将深入SwiftUI的核心概念,通过实际案例展示如何利用这一框架快速构建用户界面,并探讨其对iOS应用开发流程的影响。
|
2月前
|
移动开发 网络协议 小程序
基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v9.1版已发布
RainbowChat是一套基于开源IM聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题
59 5
|
2月前
|
Swift iOS开发 开发者
探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】在苹果生态系统中,SwiftUI的引入无疑为iOS应用开发带来了革命性的变化。本文将通过深入浅出的方式,带领读者了解SwiftUI的基本概念、核心优势以及如何在实际项目中运用这一框架。我们将从一个简单的例子开始,逐步深入到更复杂的应用场景,让初学者能够快速上手,同时也为有经验的开发者提供一些深度使用的技巧和策略。
49 1
|
2月前
|
存储 安全 开发工具
百度公共IM系统的Andriod端IM SDK组件架构设计与技术实现
本文主要介绍了百度公共IM系统的Andriod端IM SDK的建设背景、IM SDK主要结构和工作流程以及建设过程遇到的问题和解决方案。
55 3
|
3月前
|
iOS开发 开发者 UED
探索iOS应用开发中的SwiftUI框架
【9月更文挑战第26天】 在iOS开发的海洋中,SwiftUI犹如一艘现代的快艇,引领着开发者们驶向更加高效与直观的编程体验。本文将带你领略SwiftUI的魅力,从其设计理念到实际应用,我们将一步步揭开它如何简化界面构建过程的面纱。通过对比传统方式,你将看到SwiftUI如何让代码变得像诗一样优美,同时保持强大的功能性和灵活性。准备好让你的iOS开发技能加速升级,一起驾驭这股新潮流吧!
|
3月前
|
前端开发 iOS开发 开发者
探索iOS开发中的SwiftUI框架
【9月更文挑战第21天】在iOS应用开发的广阔天地中,SwiftUI框架如一股清新之风,为开发者带来了声明式语法的便捷与高效。本文将深入探讨SwiftUI的核心概念、布局方式及数据绑定机制,同时通过实例演示如何运用SwiftUI构建用户界面,旨在引领读者领略SwiftUI的魅力,并激发其对iOS开发新趋势的思考与实践。
43 6
|
3月前
|
开发工具 Swift iOS开发
探索iOS开发中的SwiftUI框架
【9月更文挑战第1天】在本文中,我们将一起潜入iOS开发的海洋,特别聚焦于SwiftUI这一现代且富有表现力的框架。SwiftUI不仅简化了界面设计流程,还为开发者提供了声明式Swift语法的便利。通过这篇文章,你将学会如何利用SwiftUI构建灵活且响应式的用户界面,并理解其背后的原理。无论你是刚入门的新手还是寻求进阶的开发者,本文都将为你提供有价值的指导和启示。
|
11天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
2天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。

热门文章

最新文章