2

I am trying to implement background music into an app I am making in Xcode, I am having trouble finding a solution that works in the current version of Swift I'm using (4.2). Currently when I segue from one view controller to another the music will restart, but this doesn't happen when I dismiss the view controller.

I will post the code I'm working on so far:

ViewController.swift

import UIKit
import AVFoundation

class ViewController: UIViewController {

var audioPlayer : AVAudioPlayer?
var selectedSoundFileName : String = ""
let phonicSoundArray = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "ai", "ar", "ch", "ck", "ee", "ie", "ng", "oa", "oi", "oo", "or", "ou", "ph", "qu", "sh", "ss", "th", "ue"]

override func viewDidLoad() {
    super.viewDidLoad()
    MusicHelper.sharedHelper.playBackgroundMusic()
}


@IBAction func dismissCurrentView(_ sender: Any) {
    self.dismiss(animated: true, completion: nil)
}

//== Phonic audio playback =================
@IBAction func phonicPracticeButtonPressed(_ sender: AnyObject) {

    selectedSoundFileName = phonicSoundArray[sender.tag - 1]+".mp3"

    let path = Bundle.main.path(forResource: selectedSoundFileName, ofType:nil)!
    let url = URL(fileURLWithPath: path)

    do {
        audioPlayer = try AVAudioPlayer(contentsOf: url)
        audioPlayer?.play()
    } catch {
        print("Couldn't load audio")
    }
}
}

BGMSingleton.swift

import Foundation
import AVFoundation

class MusicHelper {
static let sharedHelper = MusicHelper()
var audioPlayer: AVAudioPlayer?

func playBackgroundMusic() {
    let aSound = NSURL(fileURLWithPath: Bundle.main.path(forResource: "BGM", ofType: "mp3")!)
    do {
        audioPlayer = try AVAudioPlayer(contentsOf:aSound as URL)
        audioPlayer!.numberOfLoops = -1
        audioPlayer!.prepareToPlay()
        audioPlayer!.play()
    }
    catch {
        print("Cannot play the file")
    }
}
}

1 Answers1

0

Assuming you are segueing between two of the same VCs which you have posted...

Whenever you segue to a VC with MusicHelper.sharedHelper.playBackgroundMusic() in its viewDidLoad, your music will restart.

viewDidLoad occurs once per VC lifecycle. When you dismiss a VC, you are not calling its viewDidLoad which is why the music is not restarting.

More info on VC lifecycles

https://developer.apple.com/documentation/uikit/uiviewcontroller

Looking to understand the iOS UIViewController lifecycle

Mocha
  • 2,035
  • 12
  • 29
  • Thank you for your answer. What would be a more suitable location for the code: MusicHelper.sharedHelper.playBackgroundMusic() – Billy Boampong Feb 28 '19 at 02:51
  • @BillyBoampong Depends where you want the background music to start. Placing it in viewDidLoad is fine, but I don't know why you would segue to the same VC. – Mocha Feb 28 '19 at 06:06
  • Some VCs are without an accompanying swift file and are managed just through the storyboard interface as they are simple navigation screens with no need for data to be passed over. Would I be right in saying that if I wanted background music to continue playing I would need a swift file for each VC? – Billy Boampong Feb 28 '19 at 12:58
  • I did a bit of thinking and took it out of **ViewController.swift** and put it in **AppDelegate.swift** under: `func application(_ application:` `UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool` `{ MusicHelper.sharedHelper.playBackgroundMusic()` `// Override point for customization after application launch. return true }` – Billy Boampong Feb 28 '19 at 15:50
  • It seems to be working fine now, thanks for your help. – Billy Boampong Feb 28 '19 at 15:56
  • Putting it in app delegate works if you want the music to start immediately, but if you want to wait until after a load screen you would put it in the corresponding vc. Im not too familiar with storyboards do I cannot help you with how your vcs are organized. – Mocha Feb 28 '19 at 16:18