iOS更新后MPMusicPlayerController的setCurrentPlaybackRate调用失效报错
解决iOS新版本中MPMusicPlayerController setCurrentPlaybackRate失效的问题
这个"No commands provided"的错误我之前帮不少开发者排查过,本质是iOS版本更新后,MPMusicPlayerController的API调用上下文要求变严格了。下面是几个经过验证的解决方案:
1. 先确保播放器有可操作的播放上下文
这是最常见的触发原因:调用setCurrentPlaybackRate:时,播放器还没有加载有效的播放项或处于停止状态。你需要先做这几步检查:
- 确认
player.nowPlayingItem不为空,如果为空,先通过setQueueWithItemCollection:或setQueueWithStoreIDs:加载播放内容; - 确认播放器的
playbackState不是MPMusicPlaybackStateStopped,可以先启动播放,再调整速率。
示例代码:
// Objective-C MPMusicPlayerController *player = [MPMusicPlayerController applicationMusicPlayer]; if (player.nowPlayingItem && player.playbackState != MPMusicPlaybackStateStopped) { [player setCurrentPlaybackRate:0.67]; } else { // 先加载播放队列并启动播放 MPMediaItemCollection *collection = [MPMediaItemCollection collectionWithItems:@[yourMediaItem]]; [player setQueueWithItemCollection:collection]; [player play]; // 延迟一点确保播放状态更新后再设置速率 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [player setCurrentPlaybackRate:0.67]; }); }
// Swift let player = MPMusicPlayerController.applicationMusicPlayer if player.nowPlayingItem != nil && player.playbackState != .stopped { player.currentPlaybackRate = 0.67 } else { let collection = MPMediaItemCollection(items: [yourMediaItem]) player.setQueue(with: collection) player.play() DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { player.currentPlaybackRate = 0.67 } }
2. 改用MPCPlayerCommandCenter的API(iOS 13+推荐)
iOS 13之后苹果更推荐用MPCPlayerCommandCenter来控制播放,它的上下文检查更灵活,能避免这类错误:
// Swift let commandCenter = MPCPlayerCommandCenter.shared() if let rateCommand = commandCenter.playbackRateCommand { rateCommand.setPlaybackRate(0.67) { success, error in if let error = error { print("设置速率失败:\(error.localizedDescription)") } else { print("速率设置成功") } } }
// Objective-C MPCPlayerCommandCenter *commandCenter = [MPCPlayerCommandCenter sharedCommandCenter]; MPCPlayerPlaybackRateCommand *rateCommand = commandCenter.playbackRateCommand; if (rateCommand) { [rateCommand setPlaybackRate:0.67 completionHandler:^(BOOL success, NSError * _Nullable error) { if (error) { NSLog(@"设置速率失败:%@", error.localizedDescription); } else { NSLog(@"速率设置成功"); } }]; }
3. 监听播放状态通知,确保调用时机正确
不要在播放器初始化后立即调用速率设置,最好监听MPMusicPlayerControllerPlaybackStateDidChangeNotification,等播放状态变为playing或paused时再执行调整:
// Swift NotificationCenter.default.addObserver(forName: .MPMusicPlayerControllerPlaybackStateDidChange, object: player, queue: .main) { [weak self] _ in guard let self = self else { return } if player.playbackState == .playing || player.playbackState == .paused { player.currentPlaybackRate = 0.67 } } // 记得在合适的生命周期节点移除观察者
错误原因说明
iOS更新后,苹果收紧了MPMusicPlayerController的API调用限制:必须确保播放器处于有可执行命令的状态(即存在播放项且未停止),否则就会抛出"No commands provided"的错误。上面的方案都是围绕确保播放上下文有效,或者使用更适配新版本的API来解决问题。
内容的提问来源于stack exchange,提问作者TheJeff
相关产品推荐
相关产品推荐

