AVAudioPlayer在模拟器上工作,但不在真实设备上

当我播放录制的audio时,我得到这个错误:

致命错误:意外地发现零,而解包一个可选值

在这行代码中:

SoundPlayer = try AVAudioPlayer(contentsOfURL: getFileURL()) 

但是,除了真实的设备之外,它在模拟器上是完美的。

ViewController.Swift:

 import UIKit import AVFoundation class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate { @IBOutlet var PlayBTN: UIButton! @IBOutlet var RecordBTN: UIButton! var soundRecorder : AVAudioRecorder! var SoundPlayer : AVAudioPlayer! var fileName = "audioFile.m4a" override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. setupRecorder() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func setupRecorder(){ let recordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)), AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)), AVNumberOfChannelsKey : NSNumber(int: 1), AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Max.rawValue))] do{ try soundRecorder = AVAudioRecorder(URL: getFileURL(), settings: recordSettings) soundRecorder.delegate = self soundRecorder.prepareToRecord() } catch let error as NSError { error.description } } func getCacheDirectory() -> String { let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) return paths[0] } func getFileURL() -> NSURL{ let path = (getCacheDirectory() as NSString).stringByAppendingPathComponent(fileName) let filePath = NSURL(fileURLWithPath: path) return filePath } @IBAction func Record(sender: UIButton) { if sender.titleLabel?.text == "Record"{ soundRecorder.record() sender.setTitle("Stop", forState: .Normal) PlayBTN.enabled = false } else{ soundRecorder.stop() sender.setTitle("Record", forState: .Normal) PlayBTN.enabled = false } } @IBAction func PlaySound(sender: UIButton) { if sender.titleLabel?.text == "Play" { RecordBTN.enabled = false sender.setTitle("Stop", forState: .Normal) preparePlayer() SoundPlayer.play() } else{ SoundPlayer.stop() sender.setTitle("Play", forState: .Normal) } } func preparePlayer(){ do{ SoundPlayer = try AVAudioPlayer(contentsOfURL: getFileURL()) SoundPlayer.delegate = self SoundPlayer.volume = 1.0 SoundPlayer.prepareToPlay() } catch let error as NSError { error.description } } func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) { PlayBTN.enabled = true } func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) { RecordBTN.enabled = true PlayBTN.setTitle("Play", forState: .Normal) } @IBAction func actDone(sender: AnyObject) { //viewRecorder.hidden = true let fm = NSFileManager.defaultManager() let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String do { let items = try fm.contentsOfDirectoryAtPath(documentsDirectory) for item in items { print(item) } } catch let error as NSError { error.description } } } 

ViewController.Swift的Storyboard文件:

在这里输入图像说明

附加信息:

  • Xcode版本:7.2.1
  • 设备:iPhone 5s
  • iOS版本:9.2.1

注:我已经寻找类似的SO解决scheme,但没有一个帮助我。 其中一些由于较旧的Swift版本和不赞成使用的方法。 有些解决scheme是关于从应用程序包中播放audio文件,有些则使用url。 所以这种情况是不同的( Real Device vs Simulator

以下是Google云端硬盘上的源代码链接。

在真实的设备上,它需要为setCategory()设置AVAudioSession.sharedInstance()

而且一个固定的项目也可以在这里下载。

 func setupRecorder(){ let audioSession = AVAudioSession.sharedInstance() do { try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord) } catch let error as NSError { print(error.description) } let recordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)), AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)), AVNumberOfChannelsKey : NSNumber(int: 1), AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Max.rawValue))] do{ try soundRecorder = AVAudioRecorder(URL: getFileURL(), settings: recordSettings) soundRecorder.delegate = self soundRecorder.prepareToRecord() } catch let error as NSError { error.description } } 

注:audio会话是您的应用和iOS之间的中介,用于configuration您的应用的audio行为。 如果我们为AVAudioSessionCategoryPlayAndRecord设置类别,我们定义iOSaudio行为以允许audioinput(logging)和输出(回放)。 推荐: audio会话编程指南