Building a music player app with AVFoundation and a singleton class in Swift allows you to create a centralized component responsible for managing audio playback throughout your app. Here’s a basic guide on how to implement this:

  1. Create Singleton Class: Start by creating a singleton class to manage the audio player. This class will encapsulate the AVFoundation framework functionalities.
import AVFoundation

class MusicPlayerManager {
    static let shared = MusicPlayerManager()

    private var audioPlayer: AVAudioPlayer?

    private init() {}

    func playMusic(withURL url: URL) {
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.prepareToPlay()
            audioPlayer?.play()
        } catch {
            print("Error playing music: \(error.localizedDescription)")
        }
    }

    func pauseMusic() {
        audioPlayer?.pause()
    }

    func stopMusic() {
        audioPlayer?.stop()
        audioPlayer = nil
    }
}

Use Singleton Class in Your App: Now you can use the MusicPlayerManager singleton throughout your app to play, pause, and stop music.

// Example usage in a view controller
import UIKit

class ViewController: UIViewController {
    let musicURL = URL(fileURLWithPath: "path_to_your_audio_file.mp3")

    override func viewDidLoad() {
        super.viewDidLoad()
        // Play music when the view loads
        MusicPlayerManager.shared.playMusic(withURL: musicURL)
    }

    @IBAction func pauseButtonTapped(_ sender: UIButton) {
        // Pause music when the pause button is tapped
        MusicPlayerManager.shared.pauseMusic()
    }

    @IBAction func stopButtonTapped(_ sender: UIButton) {
        // Stop music when the stop button is tapped
        MusicPlayerManager.shared.stopMusic()
    }
}

Handle Audio Interruptions: You may also want to handle interruptions to audio playback, such as phone calls or other audio playing in the background. You can do this by observing notifications from the NotificationCenter

NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption(_:)), name: AVAudioSession.interruptionNotification, object: nil)

@objc func handleInterruption(_ notification: Notification) {
    guard let userInfo = notification.userInfo,
        let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
        let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
            return
    }

    switch type {
    case .began:
        // Pause audio playback
        MusicPlayerManager.shared.pauseMusic()
    case .ended:
        // Resume audio playback
        MusicPlayerManager.shared.playMusic()
    }
}

With this setup, you have a singleton MusicPlayerManager class that handles audio playback using AVFoundation. You can use this class throughout your app to play, pause, and stop music, ensuring a consistent and centralized audio playback experience.