MPMusicPlayerController在iOS11.3及以上版本崩溃问题求助
嘿,这个问题我一眼就看出症结所在了——你在playPlaylist方法里犯了一个类型不匹配的错误,而iOS 11.3开始苹果收紧了API参数的校验,直接把之前系统容忍的问题变成了崩溃。
先看触发崩溃的核心代码:
- (void)playPlaylist { [musicPlayer setQueueWithItemCollection:(MPMediaItemCollection *)musicPlaylistQuery]; [musicPlayer play]; }
这里你把MPMediaQuery对象强制转换成MPMediaItemCollection传给了setQueueWithItemCollection:,但这两个类根本没有继承关系!旧版本iOS可能对这种动态类型错误睁一只眼闭一只眼,但iOS 11.3及以后的系统会直接抛出NSException,也就是你看到的崩溃日志。
修复步骤
修正队列设置逻辑
你已经在playMusic方法里通过_collections = [musicPlaylistQuery items];拿到了目标播放列表的所有歌曲,只需要用这个数组创建一个合法的MPMediaItemCollection即可:- (void)playPlaylist { // 用查询到的歌曲数组创建正确的MPMediaItemCollection MPMediaItemCollection *itemCollection = [[MPMediaItemCollection alloc] initWithItems:_collections]; [musicPlayer setQueueWithItemCollection:itemCollection]; [musicPlayer play]; }优化MusicPlayer的内存管理
你现在用全局变量musicPlayer容易出现内存管理问题,建议把它改成ViewController的属性:- 先去掉全局的
#define TESTMUSICPLAYER MPMusicPlayerController *musicPlayer; - 在ViewController的@interface里添加属性:
@property (strong, nonatomic) MPMusicPlayerController *musicPlayer; - 然后把
initializeMusicPlayer里的代码改成:- (void)initializeMusicPlayer { self.musicPlayer = [MPMusicPlayerController applicationMusicPlayer]; [self.musicPlayer setShuffleMode:MPMusicShuffleModeOff]; [self.musicPlayer setRepeatMode:MPMusicRepeatModeAll]; } - 相应地,
playPlaylist里的调用也要改成self.musicPlayer。
- 先去掉全局的
可选:升级Xcode版本
你用的Xcode 7.3.1不支持iOS 11的SDK,所以编译时根本检测不出这种类型错误。升级到Xcode 9+(支持iOS 11及以上)后,编译器会直接提示类型不匹配,帮你提前发现问题,不用等到运行时崩溃。
为什么旧版本iOS没问题?
苹果在iOS 11.3对媒体框架的API做了更严格的参数校验,之前的系统可能通过动态类型转发容忍了这种错误,但新版本直接终止了程序,这也是苹果提升系统稳定性的常规操作。
按照上面的步骤修改后,你的App应该就能在iOS 11.3+正常播放播放列表了。
内容的提问来源于stack exchange,提问作者Kevin Wheeler

