have built a music player for my project, in which the music plays and moves to the “playerviewcontroller” after an item/song has been selected from my collection view. The only issue is as the music player is initialized on the playerVC once I leave this VC the music stops. How would I make it keep on playing on all my other view controllers
Hi Kanyin,
Welcome to the code crew community.
The solution to your problem is elegantly implemented in the Match App which is part of the iOS Foundations course that you can find on the CodeWithChris website.
In broad terms you create a class to manage your sounds and inside that class you can define a single function to play a number of different sounds by passing in a value to identify the sound you want to play or you can define a function for each sound and simple call that function from anywhere inside your project.
Thank you for the response Chris.
I did do that, but I used a custom class of UINavigationController, and still behaving weird. What sub class should I make it of then?
What does your code look like, so we have a clearer picture of what you mean?
` override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
//present player
let position = indexPath.item
guard let nc = storyboard?.instantiateViewController(identifier: "MyNav") as? MyNavController else {return}
nc.songs = songs
nc.position = position
nc.playNavPlayer()
//songs
guard let vc = storyboard?.instantiateViewController(identifier: "player") as? PlayerViewController else {
return
}
vc.songs = songs
vc.position = position
navigationController?.pushViewController(vc, animated: true)
}`
This is what happens when I select the song, next one I send would be my nav custom class.
` public var position = 0
public var songs: [Song] = []
public var player: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
print(songs.count)
player?.stop()
}
func playNavPlayer() {
let song = songs[position]
let urlString = Bundle.main.path(forResource: song.trackName, ofType: "mp3")
do{
try AVAudioSession.sharedInstance().setMode(.default)///app needs to know what mode we are working on
try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
guard let urlString = urlString else { return }
player = try AVAudioPlayer(contentsOf: URL(string: urlString)!)
guard let player = player else {return}
player.volume = 0.5
player.play()
// player.numberOfLoops = -1
player.delegate = self
}
catch {
print ("Error")
}
}
`
I am guessing there is no way to achieve this? I have checked everywhere and no one knows what to do. Please what sub class should I initialise this music player in then?
Have you followed the process of adding sounds that was used in the Match App tutorial? You do not need to subclass anything. For example you can create a manager like this:
import Foundation
import AVFoundation
class SoundManager {
static var audioPlayer : AVAudioPlayer?
static func playSound() {
// Add your code here to set up the player by getting the path to the file in the Bundle. Let's assume that the file is cantTouchThat.mp3
let bundlePath = Bundle.main.path(forResource: "cantTouchThat", ofType: "mp3")
// Check that it is not nil
guard bundlePath != nil else {
print("Couldn't find sound file \(soundFilename) in the bundle")
return
}
// Create a URL from that path
let soundURL = URL(fileURLWithPath: bundlePath!)
// Set up your do {} catch {} block and inside that play the sound
do {
// Create audio player object
audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
// Play the sound
audioPlayer?.play()
} catch {
// Could not create audio player object
print("Could not create the audio player object for sound file \(soundFilename).")
}
}
}
In order to play the sound all you need to do is:
SoundManager.playSound()