首页 > 解决方案 > 每次网络请求成功后如何播放声音?

问题描述

我想在每次网络请求成功后播放声音。我有一些对象要使用 for 循环发送到服务器。在每次迭代中,我都会向服务器发送一个请求,每个请求完成后,我想播放一个声音。

我试过这个:

for object in objects {
   sendObjectToServer(object)
}

func playSound() {
  let url = Bundle.main.url(forResource: "sound", withExtension: "mp3")!
  let player = try! AVAudioPlayer(url)
  player.play()
}

func sendObjectToServer(object: Object) {
   URLSession.shared.dataTask(with url: object.url) {(data,response,error) in
     DispatchQueue.main.async {
          playSound() // doesn't play sound synchronously
        }  
    }
 }

标签: swiftavfoundationavplayer

解决方案


为什么要使用主线程进行与后台相关的操作。Dispatch.main.async仅在代码中更新您的 UI :

在物理设备上试试这个(测试和工作)

import AVFoundation

for object in objects {
   DispatchQueue.global(qos: .background).async {
     sendObjectToServer(object)
   }
}


var player: AVAudioPlayer?

func playSound() {
    guard let url = Bundle.main.url(forResource: "sound", withExtension: "mp3") else { return }

    do {
        try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)            
        try AVAudioSession.sharedInstance().setActive(true)

        /* The following line is required for the player to work on iOS 11. Change the file type accordingly*/
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)

        /* iOS 10 and earlier require the following line:
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3) */

        guard let player = player else { return }

        player.play()

    } catch let error {
        print(error.localizedDescription)
    }
}

func sendObjectToServer(object: Object) {
   URLSession.shared.dataTask(with url: object.url) {(data,response,error) in
      // Custom Logic
      playSound()
    }
 }

推荐阅读