swiftuiviewcontrollersfx

Creating Music Instance in every View Controller


I,m creating a app the use a lot of sfx and background music. But i can't find the best way to inherite this type of data through View Controllers. Do i have to initialize my audios in every view controller? But what if i want to stop a music that started in a preview VC?

This is the code that i'm using:

do {
            // Music BG
            let resourcePath = NSBundle.mainBundle().pathForResource("MusicaBg", ofType: "wav")!
            let url = NSURL(fileURLWithPath: resourcePath)
            try musicPlayer = AVAudioPlayer(contentsOfURL: url)

            // SFX for Button

            let resourcePath2 = NSBundle.mainBundle().pathForResource("botaoApertado", ofType: "wav")!
            let url2 = NSURL(fileURLWithPath: resourcePath2)
            try botaoApertado = AVAudioPlayer(contentsOfURL: url2)

        } catch let err as NSError {
            print(err.debugDescription)
        }

What's the best way to do that?


Solution

  • You're probably looking for the Singleton pattern since you need a single canonical instance of background music, that any ViewController can interact with.

    Then any time you need to change the music you simple call the corresponding method on e.g. AudioManager.sharedInstance from anywhere, and as you keep moving through the app the music will continue.

    You would probably want to start the music in your AppDelegate or FirstViewController.

    For example, with the code you've given, you might want something like

    class AudioManager {
      static let sharedInstance = AudioManager()
    
      var musicPlayer: AVAudioPlayer?
      var botaoApertado: AVAudioPlayer?
    
      private init() {
      }
    
      func startMusic() {
        do {
          // Music BG
          let resourcePath = NSBundle.mainBundle().pathForResource("MusicaBg", ofType: "wav")!
          let url = NSURL(fileURLWithPath: resourcePath)
          try musicPlayer = AVAudioPlayer(contentsOfURL: url)
    
          // SFX for Button
          let resourcePath2 = NSBundle.mainBundle().pathForResource("botaoApertado", ofType: "wav")!
          let url2 = NSURL(fileURLWithPath: resourcePath2)
          try botaoApertado = AVAudioPlayer(contentsOfURL: url2)
    
        } catch let err as NSError {
          print(err.debugDescription)
        }
      }
    }
    
    func stopMusic() { // implementation
    }
    

    As soon as you write AudioManager.sharedInstance.startMusic() the sharedInstance static variable will be initialized (once, since it's a static property) and then startMusic() will be called on it.

    If you later call AudioManager.sharedInstance.stopMusic() it will use the same sharedInstance you initialized previously, and stop the music.

    Post any questions you have in the comments.