[英]AVAudioPlayer working on Simulator but not on Real Device
While I play recorded Audio I get this error: 当我播放录制的音频时,我收到此错误:
fatal error: unexpectedly found nil while unwrapping an Optional value
致命错误:在展开Optional值时意外发现nil
on this line of code: 在这行代码上:
SoundPlayer = try AVAudioPlayer(contentsOfURL: getFileURL())
But it is working perfectly on Simulator except real device. 但它在模拟器上完美运行,除了真实设备。
ViewController.Swift: 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
}
}
}
Storyboard file for ViewController.Swift: ViewController.Swift的Storyboard文件:
Additional info: 附加信息:
Note: I have looked for similar SO solutions but none of them helped me. 注意:我已经寻找类似的SO解决方案,但没有一个帮助我。 Some of them due to older Swift version and deprecated method.
其中一些是由于较旧的Swift版本和不推荐使用的方法。 Some solutions were regarding playing audio file from application bundle and some of were using web URLs.
一些解决方案涉及从应用程序包播放音频文件,一些使用Web URL。 So, this case is different( Real Device vs Simulator )
所以,这种情况不同( Real Device vs Simulator )
Here is the link of source code on Google Drive . 以下是Google云端硬盘中源代码的链接。
On a real device, it needs to setCategory()
for AVAudioSession.sharedInstance()
在真实设备上,需要为
setCategory()
设置AVAudioSession.sharedInstance()
And a fixed project can be downloaded here too. 这里也可以下载固定项目。
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
}
}
NOTE: An audio session is the intermediary between your app and iOS used to configure your app's audio behaviour. 注意:音频会话是您的应用和iOS之间的中介,用于配置应用的音频行为。 If we set category for
AVAudioSessionCategoryPlayAndRecord
, we define iOS audio behaviour to allow audio input (recording) and output (playback). 如果我们为
AVAudioSessionCategoryPlayAndRecord
设置类别,我们定义iOS音频行为以允许音频输入(录制)和输出(播放)。 Referred from: Audio Session Programming Guide 参考: 音频会话编程指南
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.