iOS锁屏音频播放控件不显示问题求助
排查锁屏音频控件不显示的问题
从你贴的代码来看,核心问题是没正确配置MPNowPlayingInfoCenter,另外还有几处细节需要调整,我来一步步帮你搞定:
1. 补全并正确设置NowPlaying信息
你的setupLockScreen函数只初始化了部分元数据,但没把它赋值给系统的MPNowPlayingInfoCenter——这是锁屏控件不显示的关键,系统需要这些信息才知道要渲染播放控件。而且你还搞混了「总时长」和「已播放时长」的字段,我帮你修正并抽离出复用的更新方法:
func setupLockScreen(){ let commandCenter = MPRemoteCommandCenter.shared() // 保留你已有的播放命令逻辑,补充状态更新 commandCenter.playCommand.isEnabled = true commandCenter.playCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in guard let player = self.player else { return .commandFailed } if player.rate == 0.0 { player.play() self.updateNowPlayingState(isPlaying: true) return .success } return .commandFailed } // 必须补充暂停命令,否则控件的暂停按钮会失效 commandCenter.pauseCommand.isEnabled = true commandCenter.pauseCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in guard let player = self.player else { return .commandFailed } if player.rate != 0.0 { player.pause() self.updateNowPlayingState(isPlaying: false) return .success } return .commandFailed } // 初始化基础播放信息 self.updateNowPlayingState(isPlaying: true) } // 单独抽离更新方法,方便播放状态变化时调用 private func updateNowPlayingState(isPlaying: Bool) { guard let player = self.player, let currentItem = player.currentItem else { return } var nowPlayingInfo = [String: Any]() nowPlayingInfo[MPMediaItemPropertyTitle] = "My Song" nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = currentItem.duration.seconds // 总时长 nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player.currentTime() // 当前播放进度 nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = isPlaying ? 1.0 : 0.0 // 播放状态 // 关键:把信息同步给系统 MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo }
2. 简化AppDelegate的音频会话配置
你在setupAudioSession里调用的self.becomeFirstResponder()其实没什么用(AppDelegate作为UIResponder子类,这个操作对音频会话没帮助),可以删掉,同时简化激活逻辑:
func setupAudioSession(){ do { try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: []) try AVAudioSession.sharedInstance().setActive(true) print("AVAudioSession is Active") } catch let error as NSError { print("Audio Session Error: \(error.localizedDescription)") } }
另外,UIApplication.shared.beginReceivingRemoteControlEvents在iOS 7之后已经不需要手动调用了,MPRemoteCommandCenter会自动处理,留着也不影响,但可以考虑删掉。
3. 确认后台模式配置到位
除了代码,还要检查项目配置:
- 打开Xcode的
Signing & Capabilities标签 - 添加
Background Modes能力 - 勾选
Audio, AirPlay, and Picture in Picture选项 - 或者直接在Info.plist里添加
UIBackgroundModes数组,包含audio字符串
4. 时机:在播放开始后调用setupLockScreen
要等你的音频播放器真正开始播放(比如调用player.play()之后)再调用setupLockScreen,因为此时播放器才有currentItem,能获取到正确的时长信息。比如在播放按钮的点击事件里:
@IBAction func playButtonTapped(_ sender: UIButton) { if player?.rate == 0.0 { player?.play() setupLockScreen() } else { player?.pause() updateNowPlayingState(isPlaying: false) } }
额外小提示
- 如果用的是AVPlayer,可以监听
AVPlayerItemDidPlayToEndTime通知,在播放结束时更新NowPlaying信息 - 可以监听播放器的
rate属性变化,自动同步播放状态到系统,不用手动调用更新方法
内容的提问来源于stack exchange,提问作者Nayef




