Как воспроизвести звук в приложении iOS на Swift?
Проблема: неправильная настройка аудиосессии и подготовка плеера
Ваша ошибка (OSStatus 1954045808) — это код kAudioFileUnsupportedDataFormatError. Она возникает, когда AVAudioPlayer не может декодировать файл. Чаще всего это связано с тем, что файл не добавлен в Bundle или имеет неподдерживаемый формат. Но есть и вторая, более скрытая причина: аудиосессия не активирована.
Правильное решение
Вот рабочий пример с полной настройкой:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
setupAudioSession()
}
// 1. Настраиваем аудиосессию
private func setupAudioSession() {
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Ошибка настройки аудиосессии: \(error.localizedDescription)")
}
}
// 2. Воспроизведение звука
@IBAction func playSound(_ sender: UIButton) {
guard let url = Bundle.main.url(forResource: "sound", withExtension: "mp3") else {
print("Файл не найден в Bundle")
return
}
do {
player = try AVAudioPlayer(contentsOf: url)
player?.prepareToPlay() // подготовка к воспроизведению
player?.play()
} catch {
print("Ошибка воспроизведения: \(error.localizedDescription)")
}
}
}
Ключевые моменты:
- Аудиосессия — обязательно вызывайте
setCategory(.playback)иsetActive(true)до воспроизведения. Категория .playback позволяет звуку играть даже в беззвучном режиме. - Проверка Bundle — используйте
Bundle.main.url(forResource:withExtension:)вместо path, это надёжнее. - prepareToPlay() — подготавливает буфер, уменьшает задержку при первом воспроизведении.
- Форматы файлов: поддерживаются .mp3, .wav, .aac, .m4a. Убедитесь, что файл действительно добавлен в target (галочка в "Add to targets").
Для коротких звуковых эффектов (SystemSound)
Если вам нужно проиграть короткий звук (до 30 секунд) без управления громкостью/паузой, используйте AudioToolbox — он проще и быстрее:
import AudioToolbox
// Воспроизведение системного звука
AudioServicesPlaySystemSound(1000) // звук "входящее сообщение"
// Воспроизведение своего файла
if let soundURL = Bundle.main.url(forResource: "click", withExtension: "wav") {
var soundID: SystemSoundID = 0
AudioServicesCreateSystemSoundID(soundURL as CFURL, &soundID)
AudioServicesPlaySystemSound(soundID)
}
Почему ваш код не работал?
- Отсутствовала настройка аудиосессии — iOS блокирует воспроизведение, если сессия не активирована.
- Force unwrap
path— если файл не найден, приложение упадёт с крашем. - Файл мог быть не скопирован в Bundle — проверьте, что в "Build Phases" → "Copy Bundle Resources" есть ваш файл.
Теперь ваш звук будет работать! Для коротких эффектов рекомендую SystemSound — он не требует создания экземпляра плеера и работает быстрее.
<<Альтернатива: AVAudioPlayer с делегатом и обработкой ошибок
Если вам нужно больше контроля (например, отслеживать окончание воспроизведения или обрабатывать прерывания), используйте делегат AVAudioPlayerDelegate:
class ViewController: UIViewController, AVAudioPlayerDelegate {
var player: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
setupAudio()
}
private func setupAudio() {
guard let url = Bundle.main.url(forResource: "sound", withExtension: "mp3") else { return }
do {
player = try AVAudioPlayer(contentsOf: url)
player?.delegate = self
player?.prepareToPlay()
} catch {
print("Ошибка: \(error)")
}
}
@IBAction func play(_ sender: UIButton) {
player?.play()
}
// Делегат: вызывается когда звук закончился
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
print("Воспроизведение завершено. Успешно: \(flag)")
// Можно перезапустить или сделать что-то ещё
}
// Обработка прерываний (звонок, другой звук)
func audioPlayerBeginInterruption(_ player: AVAudioPlayer) {
player.pause()
}
func audioPlayerEndInterruption(_ player: AVAudioPlayer, withOptions flags: Int) {
player.play()
}
}
Также обратите внимание: для длительного воспроизведения (музыка, подкасты) лучше использовать AVPlayer (более мощный), а для простых звуков — AVAudioPlayer или SystemSound. Не забывайте вызывать player?.stop() и обнулять плеер при уходе с экрана, чтобы избежать утечек памяти.