While I play recorded Audio I get this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
on this line of code:
SoundPlayer = try AVAudioPlayer(contentsOfURL: getFileURL())
But it is working perfectly on Simulator except real device.
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:
Additional info:
- Xcode version : 7.2.1
- Device : iPhone 5s
- iOS version : 9.2.1
Note: I have looked for similar SO solutions but none of them helped me. Some of them due to older Swift version and deprecated method. Some solutions were regarding playing audio file from application bundle and some of were using web URLs. So, this case is different(Real Device vs Simulator)
Here is the link of source code on Google Drive.