《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表示用户的预定义首选模式。

相关文章
|
搜索推荐 数据管理 定位技术
iOS应用开发中有多种主流框架
iOS应用开发中有多种主流框架
862 60
|
7月前
|
数据采集 监控 API
移动端性能监控探索:iOS RUM SDK 技术架构与实践
阿里云 RUM SDK 作为一款性能体验监控采集工具,可以作为辅助 App 运维的强有力助手,提升您的问题排查效率。
408 60
|
移动开发 网络协议 小程序
基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v10.0版已发布
RainbowChat是一套基于开源IM即时通讯聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题。RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品。与姊妹产品RainbowTalk和RainbowChat-Web 技术同源,历经考验。
706 0
基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v10.0版已发布
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
969 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
471 66
|
前端开发 JavaScript 开发工具
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
997 5
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
iOS开发 开发者
探索iOS开发中的SwiftUI框架
【10月更文挑战第39天】在苹果的生态系统中,SwiftUI框架以其声明式语法和易用性成为开发者的新宠。本文将深入SwiftUI的核心概念,通过实际案例展示如何利用这一框架快速构建用户界面,并探讨其对iOS应用开发流程的影响。
263 1
|
Swift iOS开发 开发者
探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】在苹果生态系统中,SwiftUI的引入无疑为iOS应用开发带来了革命性的变化。本文将通过深入浅出的方式,带领读者了解SwiftUI的基本概念、核心优势以及如何在实际项目中运用这一框架。我们将从一个简单的例子开始,逐步深入到更复杂的应用场景,让初学者能够快速上手,同时也为有经验的开发者提供一些深度使用的技巧和策略。
296 1
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。
|
8月前
|
开发工具 Android开发
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
824 11
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡