问题
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