使用MusicKit ApplicationMusicPlayer播放大音乐集合时遇远程调用超时错误
解决MusicKit大播放列表初始化超时问题
方案1:分批初始化队列并追加
一次性传入大量QueueEntry会触发远程调用超时,可先初始化小批量基础队列,再分批追加剩余歌曲:
typealias QueueEntry = ApplicationMusicPlayer.Queue.Entry let player = ApplicationMusicPlayer.shared let entries: [QueueEntry] = tracks.compactMap { guard let song = $0 as? Song else { return nil } return QueueEntry(song) } Task(priority: .high) { [player] in do { // 先初始化前200首作为基础队列 let initialBatch = Array(entries.prefix(200)) player.queue = .init(initialBatch, startingAt: nil) // 分批追加剩余歌曲,每批100首,追加后短暂等待避免服务过载 let remaining = Array(entries.dropFirst(200)) for batch in remaining.chunked(into: 100) { player.queue.append(batch) try await Task.sleep(nanoseconds: 50_000_000) // 等待50ms } try await player.play() } catch { print(error) } } // 给Array添加分块扩展 extension Array { func chunked(into size: Int) -> [[Element]] { return stride(from: 0, to: count, by: size).map { Array(self[$0..<Swift.min($0 + size, count)]) } } }
方案2:MPMusicPlayerController分批处理播放参数
改用MPMusicPlayerController时,同样通过分批设置队列+追加的方式规避超时:
let player = MPMusicPlayerController.systemMusicPlayer let playParams: [MPMusicPlayerPlayParameters] = tracks.compactMap { guard let song = $0 as? Song, let id = song.id else { return nil } return MPMusicPlayerPlayParameters(identifier: id.rawValue, kind: .song) } Task(priority: .high) { [player] in do { let initialBatch = Array(playParams.prefix(200)) player.setQueue(with: initialBatch) let remaining = Array(playParams.dropFirst(200)) for batch in remaining.chunked(into: 100) { player.append(batch) try await Task.sleep(nanoseconds: 50_000_000) } player.play() } catch { print(error) } }
方案3:优先播放首歌+后台追加队列
如果需要立即响应用户播放操作,可先初始化仅含第一首歌的队列,再在后台分批追加剩余内容:
Task(priority: .high) { [player] in do { guard let firstEntry = entries.first else { return } // 先初始化仅含第一首的队列,立即播放 player.queue = .init([firstEntry], startingAt: firstEntry) try await player.play() // 后台分批追加剩余歌曲 let remainingEntries = Array(entries.dropFirst()) for batch in remainingEntries.chunked(into: 100) { player.queue.append(batch) try await Task.sleep(nanoseconds: 50_000_000) } } catch { print(error) } }
核心原因说明
MPMusicPlayerControllerErrorDomain Code=9本质是MusicKit远程服务处理大量请求超时,分批操作能减少单次请求的数据量,从根源避免超时触发。分块大小建议在100-200之间,间隔时间可根据设备性能微调,50-100ms即可,完全不影响自定义排序的需求。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

