How do I get music to persist as I navigate from view to view?

让人想犯罪 __ 提交于 2019-12-11 02:22:55

问题


So, I have mastered the art of playing sounds/music using one view in iOS, but I am now trying to make a more robust app for an musical artist. Thus far, it involves segues from a "menu" ViewController to his Bio, Show Times, and "Listening Room" etc. Thus far, I created a an "AudioManager" class:

import UIKit
import AVFoundation
import MediaPlayer

class AudioManager: NSObject {

    let defaltSong = ["Hell&BackCaf/01 Black Sheep", "caf"]
    weak var delegate : PlayerDelegate?
    var musicPlayer1 = AVAudioPlayer()
    var trackNumber = 0

    var musicAudioPath = NSBundle.mainBundle().pathForResource("Hell&BackCaf/01 Black Sheep", ofType: "caf")
    var musicAudioPathURL = NSURL()
    var error:NSError? = nil


    var songList = [["Hell&BackCaf/01 Black Sheep", "caf"], ["Hell&BackCaf/02 Hell & Back", "caf"], ["Hell&BackCaf/03 Save Me", "caf"], ["Hell&BackCaf/04 Broken feat. Hillary Dodson", "caf"], ["Hell&BackCaf/05 Do Or Die", "caf"], ["Hell&BackCaf/06 Divided", "caf"]]

    func ButtonPlay(song: NSString, type: NSString) {

        error = nil

        musicAudioPath = NSBundle.mainBundle().pathForResource(song as String, ofType: type as String)

        musicAudioPathURL = NSURL(fileURLWithPath: self.musicAudioPath!)!

        musicPlayer1 = AVAudioPlayer(contentsOfURL: musicAudioPathURL, error: &error)

        musicPlayer1.prepareToPlay()

        musicPlayer1.play()
    }

    func loadFirstSong() {

        error = nil

        musicAudioPath = NSBundle.mainBundle().pathForResource("Hell&BackCaf/01 Black Sheep", ofType: "caf")
        musicAudioPathURL = NSURL(fileURLWithPath: self.musicAudioPath!)!
        musicPlayer1 = AVAudioPlayer(contentsOfURL: musicAudioPathURL, error: &error)
        if error == nil {
            musicPlayer1.prepareToPlay()
        } else {
            println(error)
        }


    }


    func advanceTrack(){

        if trackNumber < songList.count - 1 {

            self.trackNumber++

            ButtonPlay(songList[trackNumber][0], type: songList[trackNumber][1])            
        } else {

            trackNumber = 0

            ButtonPlay(songList[trackNumber][0], type: songList[trackNumber][1])
        }
    }

    func previousTrack(){

        if trackNumber > 0 {

            trackNumber--

            ButtonPlay(songList[trackNumber][0], type: songList[trackNumber][1])

        } else {

            trackNumber = songList.count - 1

            ButtonPlay(songList[trackNumber][0], type: songList[trackNumber][1])
        }

    }

    func audioPlayerDidFinishPlaying(AVAudioPlayer!, successfully: Bool) {
        self.delegate?.soundFinished(self)
        println("song over")
    }



}

I then used it in my MusicRoomViewController:

import UIKit
import AVFoundation

class MusicRoomViewController: UIViewController, AVAudioPlayerDelegate {

    let audioManager = AudioManager()

    @IBAction func pressedBackButton(sender: UIButton) {
        audioManager.previousTrack()
    }

    @IBAction func pressedPlayButton(sender: UIButton) {
        audioManager.musicPlayer1.play()
    }

    @IBAction func pressedForwardButton(sender: UIButton) {
        audioManager.advanceTrack()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        audioManager.loadFirstSong()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func viewWillDisappear(animated: Bool) {

        if self.isMovingFromParentViewController()
        {
            audioManager.musicPlayer1.play()
        }
    }

}

But now when I navigate to any other 'page' of the app, the music stops. After researching, I know that I am going about this all wrong, but I can't seem to figure out what I need to do to keep the audio playing until the app is closed or the user presses stop (which does not exist yet, I know). Any thoughts??


回答1:


You're going to have to make your AudioManager class a singleton. What is happening, is the AudioManager instance you're creating is being deallocated once you navigate away from the view you created it in. A singleton object is created once it is first accessed, and will persist in memory until the application's lifecycle ends or it is explicitly deallocated. For more information on Swift singletons, check out this page. It's a useful pattern to learn.

Make the following modifications to AudioManager (taken from the above website):

private let _AudioManagerSharedInstance = AudioManager()

class AudioManager {
    static let sharedInstance = AudioManager()
}

Access AudioManager by using AudioManager.sharedInstance, for example you can call AudioManager.sharedInstance.previousTrack().




回答2:


You could create a singleton, or instantiate the AudioManager in your AppDelegate class and refer to that like so:

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

appDelegate.audioManger...


来源:https://stackoverflow.com/questions/29908760/how-do-i-get-music-to-persist-as-i-navigate-from-view-to-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!