【问题标题】:Unable to get AVAudioPlayer to stop playing无法让 AVAudioPlayer 停止播放
【发布时间】:2021-04-22 18:15:32
【问题描述】:

我有一个定义为 Music.swift 的类,编码如下:

import Foundation
import AVFoundation

class Music {

   var isPlaying: Bool = false
   public var backgrndSound = AVAudioPlayer()
      
   func isMusicPlaying() -> Bool {
      isPlaying = UserDefaults.standard.bool(forKey: "isPlaying")
      return isPlaying
   }
   
   func StartPlaying() {
      let path = Bundle.main.path(forResource: "Music.mp3", ofType: nil)!
      let url = URL(fileURLWithPath: path)
      do {
         self.backgrndSound = try AVAudioPlayer(contentsOf: url)
         self.backgrndSound.numberOfLoops = -1
         self.backgrndSound.play()
         UserDefaults.standard.setValue(true, forKey: "isPlaying")
      } catch {
         // couldn't load file :(
      }
   }
   
   func StopPlaying() {
      self.backgrndSound.pause()
      self.backgrndSound.stop()
   }  
}

首次加载应用时,音乐会通过调用 StartPlaying() 自动开始。这工作得很好。之后我有一个设置菜单,其中有一个音乐播放开关:


import UIKit
import AVFoundation

class SettingsViewController: UIViewController {

   @IBOutlet weak var swMusic: UISwitch!
   var myMusic = Music()
   
   override func viewDidLoad() {
        super.viewDidLoad()

      swMusic.isOn = UserDefaults.standard.bool(forKey: "isPlaying")
   }

   @IBAction func musicSwitch(_ sender: Any) {
      if swMusic.isOn == true {
         // turn on music
         myMusic.StartPlaying()
      } else {
         myMusic.StopPlaying()
      }
   }  
}

当我点击开关时,它会触发 StopPlaying(),但尽管点击了,背景中的音乐仍会继续播放。

我不确定为什么会这样,除非 AV 对象无法从原始创建中访问,因此无法正确停止它;但到目前为止,我也无法弄清楚。

任何帮助或建议将不胜感激。

【问题讨论】:

    标签: ios swift avfoundation avaudioplayer


    【解决方案1】:

    通过在SettingsViewController 中实例化Music 类的新实例,您实际上是在创建一个对已经实例化的实例一无所知的新AVAudioPlayer 实例。

    考虑一下这段代码,它包含 static 属性和 class 方法:

    import Foundation
    import AVFoundation
    
    class Music 
    {
    
       public static var backgrndSound: AVAudioPlayer?
    
       // AVAudioPlayer already has an isPlaying property          
       class func isMusicPlaying() -> Bool 
       {
          return backgrndSound?.isPlaying ?? false
       }
       
       class func StartPlaying() 
       {
          let path = Bundle.main.path(forResource: "Music.mp3", ofType: nil)!
          let url = URL(fileURLWithPath: path)
          do 
          {
             backgrndSound = try AVAudioPlayer(contentsOf: url)
             backgrndSound?.numberOfLoops = -1
             backgrndSound?.play()
          } 
          catch 
          {
             // couldn't load file :(
          }
       }
       
       class func StopPlaying() 
       {
          backgrndSound?.pause()
          backgrndSound?.stop()
       }  
    }
    

    然后使用:

    Music.isMusicPlaying()
    Music.startPlaying()
    Music.stopPlaying()
    

    即你不会这样做var myMusic = Music()

    这样,AVAudioPlayerMusic.backgrndSound 的单个实例将始终存在

    此示例代码将backgrndSound 更改为可选...您实际上是在创建一个未使用的AVAudioPlayer 实例,该实例在您startPlaying 时立即被丢弃。

    它还删除了不必要的isPlaying 属性,因为AVAudioPlayer 已经有一个用于此目的的属性。

    【讨论】:

    • 该死,我错过了 func 的“类”部分并且我有一个静态错误,但我感谢我的朋友的帮助和帮助。我绝对想把它封装起来,这样我就可以在任何地方使用它,而不会产生大量的意大利面条代码。
    猜你喜欢
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 2011-12-03
    • 2012-01-18
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多