16

I want the user to be able to open the app and have music start playing. I want the user to be able to go any view controller and return back to the initial one without the music stopping. I want it to loop indefinitely.

I have tried to put in the viewDidLoad method of the initial view controller for it to start playing. What happens is, the user leaves the initial view controller and when they come back, the music starts playing again, overlapping the original copy.

To remedy this, I put an if statement checking if the sound is already to playing to not launch another copy and the viewDidLoad method completely ignores the if statement and plays it again anyways. I also tried using viewDid/WillAppear. I have tried putting the sound in the app delegate in the applicationDidLaunchWithOptions method and I got complete silence.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253

8 Answers8

15

Using a singleton works as well:

Swift 3 or later

import AVFoundation

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

Swift 2.2.1 or earlier

import AVFoundation

class MusicHelper {
    static let sharedHelper = MusicHelper()
    var audioPlayer: AVAudioPlayer?
    
    func playBackgroundMusic() {
        let aSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("coolsong", ofType: "mp3")!)
        do {
            audioPlayer = try AVAudioPlayer(contentsOfURL:aSound)
            audioPlayer!.numberOfLoops = -1
            audioPlayer!.prepareToPlay()
            audioPlayer!.play()
        } catch {
            print("Cannot play the file")
        }
    }
}

Then you can use it from any class (as per Swift 2.1)

MusicHelper.sharedHelper.playBackgroundMusic()
Astri
  • 575
  • 4
  • 10
6

Here's how I did mine. Add this code anywhere OUTSIDE the class scene where you want the music to start playing. You can even make a whole new Swift file and just add this code in there (import AVFoundation)

var backgroundMusicPlayer: AVAudioPlayer!

func playBackgroundMusic(filename: String) {

    //The location of the file and its type
    let url = NSBundle.mainBundle().URLForResource(filename, withExtension: "mp3")

    //Returns an error if it can't find the file name
    if (url == nil) {
        println("Could not find the file \(filename)")
    }

    var error: NSError? = nil

    //Assigns the actual music to the music player
    backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: url, error: &error)

    //Error if it failed to create the music player
    if backgroundMusicPlayer == nil {
    println("Could not create audio player: \(error!)")
    return
    }

    //A negative means it loops forever
    backgroundMusicPlayer.numberOfLoops = -1
    backgroundMusicPlayer.prepareToPlay()
    backgroundMusicPlayer.play()
}

After you have that, go to the didMoveToView function and call the function with the name of the file.

playBackgroundMusic("IntroMusic")

I just tested it and it works perfect after switching scenes.

Hedylove
  • 1,724
  • 16
  • 26
  • Where did you define the `didMoveToView` function? – Lukesivi Nov 26 '15 at 10:53
  • 1
    Sorry for the late respond but it's a function of the superclass, SKScene. It's called when the app moves to that view. Basically didMoveToView is called when preparing the scene. So if you want the function in your class, it will have to be override func didMoveToView() – Hedylove Aug 01 '16 at 09:09
5

Swift 4.2 Update

Step 1. Make a new class "MusicHelper"

Step 2. Copy and paste code from below

import AVFoundation

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

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

Step 3. Copy and paste code from below to your view controller

import AVFoundation  //import at the top

var player: AVAudioPlayer?  //declare in code

MusicHelper.sharedHelper.playBackgroundMusic() //paste in viewDidLoad
3

Just add "numberofLoops = -1" an its plays infinitly in the background.

Example (Swift):

func playBackgroundMusic() {
    do {
        if let bundle = NSBundle.mainBundle().pathForResource("someMP3file", ofType: "mp3") {
            let alertSound = NSURL(fileURLWithPath: bundle)
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            try AVAudioSession.sharedInstance().setActive(true)
            try audioPlayer = AVAudioPlayer(contentsOfURL: alertSound)
            audioPlayer.numberOfLoops = -1
            audioPlayer.prepareToPlay()
            audioPlayer.play()

        }
    } catch {
        print(error)
    }
}

Have fun.

Ben
  • 31
  • 4
1

Found a solution. I declared a view controller property called signal. I said signal: Bool? - Then in viewDidLoad I put an if statement to only play the background song if signal == nil. Then, in my other view controllers I set it so that when they segue back to the mainviewcontroller, the signal property = false. Then, the song won't play again and everything works correctly.

1

for swift 4:

func playBackgroundMusic() {
        let aSound = NSURL(fileURLWithPath: Bundle.main.path(forResource: "music", ofType: "mp3")!)
        do {
            audioPlayer = try AVAudioPlayer(contentsOf:aSound as URL)
            audioPlayer!.numberOfLoops = -1
            audioPlayer!.prepareToPlay()
            audioPlayer!.play()
        } catch {
            print("Cannot play the file")
        }
    }
Mr Smith
  • 3,318
  • 9
  • 47
  • 85
Ruhtra Tam
  • 21
  • 1
0

solved the problem ALHAMDULELLAH only change in Xcode setting

go to setting page>>Capabilities>>Background>>modes>>Allow audio file enter image description here

M Hamayun zeb
  • 448
  • 4
  • 10
-1

I think you should try in you AppDelegate.swift file. In the method application(.....didFinishLaunchingWithOptions.....){} define your AVAudioPlayer() and .play()

Leo Lee
  • 11