Swift
AVAudioPlayer
Debugging
iOS Development
Xcode

AVAudioPlayer throws breakpoint in debug mode

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When AVAudioPlayer triggers a breakpoint in Xcode debug mode, it is almost always caused by an "All Exceptions" breakpoint catching internal Objective-C exceptions that AVFoundation throws and handles internally. These exceptions are not bugs — AVFoundation uses exception-based control flow internally, and they are caught before reaching your code. The fix is to modify your exception breakpoint to only break on your own exceptions, or to add an action that continues automatically after hitting the breakpoint.

The Problem

swift
1import AVFoundation
2
3class SoundPlayer {
4    var player: AVAudioPlayer?
5
6    func playSound() {
7        guard let url = Bundle.main.url(forResource: "click", withExtension: "wav") else {
8            return
9        }
10
11        do {
12            player = try AVAudioPlayer(contentsOf: url)
13            player?.play()  // Xcode stops here with a breakpoint!
14        } catch {
15            print("Error: \(error)")
16        }
17    }
18}

Xcode pauses execution at the play() call (or during AVAudioPlayer initialization) even though no error occurs in your code. The audio plays successfully after you continue.

Fix 1: Modify the Exception Breakpoint

In Xcode's Breakpoint Navigator:

  1. Find your "All Exceptions" breakpoint
  2. Right-click > Edit Breakpoint
  3. Change "Exception" from "All" to "Objective-C" (or "C++")
  4. Or better, add a condition or action:

Option A: Change to break only on Swift errors:

  • Exception: Swift Error

Option B: Add an auto-continue action:

  • Click "Add Action" > "Debugger Command"
  • Enter: po $arg1 (to log the exception)
  • Check "Automatically continue after evaluating actions"

Fix 2: Remove the All Exceptions Breakpoint

If you do not need to catch all Objective-C exceptions:

  1. Open the Breakpoint Navigator (Cmd+8)
  2. Find "All Exceptions" breakpoint
  3. Right-click > Delete

You can still catch Swift errors with a "Swift Error Breakpoint" which does not trigger on AVFoundation's internal exceptions.

Fix 3: Audio Session Configuration

Sometimes the breakpoint triggers because the audio session is not configured properly:

swift
1import AVFoundation
2
3class SoundPlayer {
4    var player: AVAudioPlayer?
5
6    init() {
7        configureAudioSession()
8    }
9
10    private func configureAudioSession() {
11        do {
12            let session = AVAudioSession.sharedInstance()
13            try session.setCategory(.playback, mode: .default)
14            try session.setActive(true)
15        } catch {
16            print("Audio session error: \(error)")
17        }
18    }
19
20    func playSound(named name: String) {
21        guard let url = Bundle.main.url(forResource: name, withExtension: "wav") else {
22            print("Sound file not found: \(name)")
23            return
24        }
25
26        do {
27            player = try AVAudioPlayer(contentsOf: url)
28            player?.prepareToPlay()
29            player?.play()
30        } catch {
31            print("Playback error: \(error)")
32        }
33    }
34}

Configuring the audio session before creating the player can prevent some of the internal exceptions that AVFoundation throws when it probes available audio routes.

Proper AVAudioPlayer Setup

swift
1import AVFoundation
2
3class AudioManager: NSObject, AVAudioPlayerDelegate {
4    static let shared = AudioManager()
5    private var players: [String: AVAudioPlayer] = [:]
6
7    private override init() {
8        super.init()
9        setupAudioSession()
10    }
11
12    private func setupAudioSession() {
13        do {
14            let session = AVAudioSession.sharedInstance()
15            try session.setCategory(.playback, mode: .default, options: [.mixWithOthers])
16            try session.setActive(true)
17        } catch {
18            print("Failed to configure audio session: \(error)")
19        }
20    }
21
22    func preloadSound(named name: String, extension ext: String = "wav") {
23        guard let url = Bundle.main.url(forResource: name, withExtension: ext) else {
24            print("Sound not found: \(name).\(ext)")
25            return
26        }
27
28        do {
29            let player = try AVAudioPlayer(contentsOf: url)
30            player.delegate = self
31            player.prepareToPlay()  // Pre-buffers audio data
32            players[name] = player
33        } catch {
34            print("Failed to load \(name): \(error)")
35        }
36    }
37
38    func play(_ name: String) {
39        guard let player = players[name] else {
40            print("Sound not preloaded: \(name)")
41            return
42        }
43
44        if player.isPlaying {
45            player.currentTime = 0  // Restart from beginning
46        }
47        player.play()
48    }
49
50    // MARK: - AVAudioPlayerDelegate
51    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
52        if !flag {
53            print("Playback finished with error")
54        }
55    }
56
57    func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
58        print("Decode error: \(error?.localizedDescription ?? "unknown")")
59    }
60}
61
62// Usage
63AudioManager.shared.preloadSound(named: "click")
64AudioManager.shared.preloadSound(named: "success")
65AudioManager.shared.play("click")

Debugging Real AVAudioPlayer Errors

swift
1// Common actual errors (not false breakpoints):
2// 1. File not found
3guard let url = Bundle.main.url(forResource: "sound", withExtension: "wav") else {
4    fatalError("Sound file missing from bundle — check target membership")
5}
6
7// 2. Unsupported format
8// AVAudioPlayer supports: MP3, AAC, WAV, AIFF, CAF, M4A
9// Does NOT support: OGG, FLAC (without conversion), WMA
10
11// 3. Corrupt or truncated file
12do {
13    let player = try AVAudioPlayer(contentsOf: url)
14    print("Duration: \(player.duration)s, Channels: \(player.numberOfChannels)")
15} catch {
16    print("File may be corrupt: \(error)")
17}
18
19// 4. Simulator audio issues
20#if targetEnvironment(simulator)
21print("Note: Audio behavior may differ on Simulator vs device")
22#endif

Common Pitfalls

  • Keeping "All Exceptions" breakpoint and blaming AVAudioPlayer: The internal exceptions are normal AVFoundation behavior, not bugs. They are caught internally and never propagate to your code. Modify the breakpoint to "Swift Error" only, or add auto-continue to avoid false stops.
  • Not retaining the AVAudioPlayer instance: AVAudioPlayer must be stored in a property. If it is a local variable, ARC deallocates it immediately after the function returns, stopping playback mid-stream. Always assign to a stored property: self.player = try AVAudioPlayer(...).
  • Forgetting to call prepareToPlay(): Without prepareToPlay(), the first play() call buffers audio data synchronously, causing a perceptible delay. Pre-buffer by calling prepareToPlay() during initialization, especially for short sound effects where latency matters.
  • Not configuring the audio session: Without setting the audio session category, playback may be silent when the device is in silent mode, or may interrupt other audio unexpectedly. Set .playback to play through silent mode, or .ambient to respect it. Set .mixWithOthers to avoid stopping background music.
  • Playing sounds on a background thread without audio session activation: AVAudioPlayer should be used on the main thread for UI-related sounds. If you call play() from a background thread, ensure the audio session is active. Some operations (like route changes) must happen on the main thread. Use DispatchQueue.main.async { player.play() } if unsure.

Summary

  • The breakpoint during AVAudioPlayer usage is caused by Xcode's "All Exceptions" breakpoint catching AVFoundation's internal exceptions
  • Change the exception breakpoint to "Swift Error" only, or add auto-continue to stop false positives
  • Always configure AVAudioSession before creating an AVAudioPlayer
  • Retain the player in a stored property — local variables are deallocated by ARC
  • Call prepareToPlay() to pre-buffer audio and reduce playback latency

Course illustration
Course illustration

All Rights Reserved.