使用MPMusicPlayerController私有API获取播放队列时标题返回nil的问题
解决iOS获取播放队列时MPModelSong属性无法访问的问题
看起来你踩了一个私有API使用的典型坑——虽然成功拿到了对象,但错误的类型强转导致你无法正确访问MPModelSong的属性。让我们一步步排查和解决:
核心问题分析
你通过私有Selector nowPlayingItemAtIndex: 获取到的对象本质是MPModelSong(属于MusicKit框架的模型类),但你强行把它转为了MPMediaItem(MediaPlayer框架的旧模型类)。这两个类没有继承关系,强转只是编译层面“蒙混过关”,运行时无法通过MPMediaItem的方法/属性访问MPModelSong的内部数据,所以所有title相关的调用都返回nil。
排查与修复步骤
1. 先确认对象的真实类型
在你的循环里先打印对象类型,验证这个判断:
if let mediaItem = MPMusicPlayerController.systemMusicPlayer.perform(Selector("nowPlayingItemAtIndex:"), with: i)?.takeUnretainedValue() { print("实际类型:\(type(of: mediaItem))") // 应该输出MPModelSong if let songObject = mediaItem as? NSObject { print("songObject类型:\(type(of: songObject))") } }
2. 直接处理MPModelSong对象
既然确认是MPModelSong,就不要再转成MPMediaItem,直接用KVC访问它的属性(因为是私有API,直接调用属性可能会有编译报错):
if let songObject = MPMusicPlayerController.systemMusicPlayer.perform(Selector("nowPlayingItemAtIndex:"), with: i)?.takeUnretainedValue() as? NSObject { // 直接访问MPModelSong的title属性 print(songObject.value(forKey: "title")) // 也可以尝试访问其他属性,比如歌手名 print(songObject.value(forKey: "artist")) }
3. 检查媒体库权限
如果还是拿不到值,先确认你已经请求了媒体库访问权限:
import MediaPlayer MPMediaLibrary.requestAuthorization { status in if status == .authorized { // 在这里执行获取队列的代码 } }
没有授权的话,即使拿到对象,系统也会限制你访问内容属性。
4. 改用官方API(推荐)
如果你的目标系统是iOS 10及以上,完全可以用官方公开的queue属性获取播放队列,避免私有API的风险:
let player = MPMusicPlayerController.systemMusicPlayer if let queue = player.queue as? MPMusicPlayerQueue { for queueItem in queue.items { if let song = queueItem.item as? MPModelSong { print("歌曲标题:\(song.title ?? "未知")") print("歌手:\(song.artist ?? "未知")") } } }
重要提醒
使用私有API(比如你用的nowPlayingItemAtIndex: Selector)会导致你的App无法通过App Store审核,除非你是开发企业内部应用。优先用官方公开API是更稳妥的选择。
内容的提问来源于stack exchange,提问作者user5136425
相关产品推荐
相关产品推荐

