无法触发Completion Block求助:playAudio回调不执行排查
playAudio回调未触发的原因及解决办法
问题描述
在playAudio方法中,completion(audioFileURL)处断点能正常触发,但调用该方法时传入的回调闭包(print("lala")所在的闭包)从未执行,导致歌曲无法播放。相关代码如下:
playAudio方法代码
func playAudio(url: URL, completion: (URL) -> ()) { if savedFiles.contains(where: { $0.key == url }) { let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let audioFileURL = documentsDirectoryURL.appendingPathComponent(url.lastPathComponent) do { let data = savedFiles[url] try data?.write(to: audioFileURL) completion(audioFileURL) } catch { delegate?.didCatchError() } } else { downloadSong(url: url) { [weak self] result in guard let self else { return } switch result { case .success(let result): if let url = result.first?.key { self.playAudio(url: url, completion: { _ in }) } default: break } } } }
调用代码
trackDownloader.playAudio(url: url) { [weak self] url in print("lala") guard let self else { return } self.player = AVPlayer(url: url) self.playerToggle(play: isPlaying) self.startPlayTimestamp = startPlayTimestamp.getTimeStamp() self.createProgressObserver() }
核心原因
递归调用playAudio时丢失了原始回调闭包:
- 当目标文件未在
savedFiles中时,会进入else分支执行下载逻辑。 - 下载成功后,代码递归调用
playAudio(url: url, completion: { _ in }),这里传入的是空闭包,而非用户最初调用时传入的包含print("lala")的回调闭包。 - 后续即使进入
if分支执行completion(audioFileURL),执行的也是这个空闭包,自然不会触发调用处的业务逻辑。
修复方案
修改else分支中的递归调用,将原始的completion闭包传递进去:
func playAudio(url: URL, completion: (URL) -> ()) { if savedFiles.contains(where: { $0.key == url }) { let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let audioFileURL = documentsDirectoryURL.appendingPathComponent(url.lastPathComponent) do { let data = savedFiles[url] try data?.write(to: audioFileURL) completion(audioFileURL) } catch { delegate?.didCatchError() } } else { downloadSong(url: url) { [weak self] result in guard let self else { return } switch result { case .success(let result): if let url = result.first?.key { // 传递原始的completion闭包,而非空闭包 self.playAudio(url: url, completion: completion) } default: break } } } }
额外检查点
- 确认
downloadSong成功后,是否将下载的url和对应数据正确存入savedFiles,否则递归调用可能再次进入else分支,陷入循环。 - 检查
result.first?.key是否确实是目标URL,避免因URL不匹配导致后续逻辑异常。
内容的提问来源于stack exchange,提问作者kesape
相关产品推荐
相关产品推荐

