I am in some desperate need of assistance, since my head is really sore from beating it against the wall.
I have one view controller where I am recording audio with my microphone and saving it to the apps document directory. This is working well and I can see the files if I navigate to that folder in the simulator.
My problem is that I have a TableView with its own TableViewController where I want to list the contents of that document directory that contains my recordings. I created the TableView and it is reading and populating the table based on a basic array. My problem is that I am failing to convert it over to read the Document Directory contents instead.
I have future goals for this table to also allow me play, delete, or rename the file from within this TableView via swiping the particular cell.
I have been working on this issue for about 5 days now and I am certain I am overlooking something very simple to you all.
I am using Xcode 7.3.1 with Swift 2.
Thanks in advance and I can't wait until I get to a point where I can contribute.
ViewControllerRecorder.swift (This is where I record and save the audio to the Document Directory, which is working.)
import UIKit
import AVFoundation
import PermissionScope
class ViewControllerRecorder: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate {
@IBOutlet weak var stopButton: UIButton!
@IBOutlet weak var recordButton: UIButton!
@IBOutlet weak var playButton: UIButton!
@IBOutlet weak var audioDuration: UISlider!
var audioRecorder:AVAudioRecorder?
var audioPlayer:AVAudioPlayer?
let pscope = PermissionScope()
override func viewDidLoad() {
super.viewDidLoad()
audioDuration.value = 0.0
// Set up permissions
pscope.addPermission(MicrophonePermission(),
message: "Inorder to use this app, you need to grant the microphone permission")
// Show dialog with callbacks
pscope.show({ finished, results in
print("got results \(results)")
}, cancelled: { (results) -> Void in
print("thing was cancelled")
})
// Disable Stop/Play button when application launches
stopButton.enabled = false
playButton.enabled = false
// Get the document directory. If fails, just skip the rest of the code
guard let directoryURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first else {
let alertMessage = UIAlertController(title: "Error", message: "Failed to get the document directory for recording the audio. Please try again later.", preferredStyle: .Alert)
alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alertMessage, animated: true, completion: nil)
return
}
// Set the default audio file
let audioFileURL = directoryURL.URLByAppendingPathComponent("PWAC_" + NSUUID().UUIDString + ".m4a")
// Setup audio session
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: AVAudioSessionCategoryOptions.DefaultToSpeaker)
// Define the recorder setting
let recorderSetting: [String: AnyObject] = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 32000.0,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey: AVAudioQuality.Medium.rawValue
]
// Initiate and prepare the recorder
audioRecorder = try AVAudioRecorder(URL: audioFileURL, settings: recorderSetting)
audioRecorder?.delegate = self
audioRecorder?.meteringEnabled = true
audioRecorder?.prepareToRecord()
} catch {
print(error)
}
}
func updateaudioDuration(){
audioDuration.value = Float(audioPlayer!.currentTime)
}
@IBAction func sliderAction(sender: AnyObject) {
audioPlayer!.currentTime = NSTimeInterval(audioDuration.value)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func play(sender: AnyObject) {
if let recorder = audioRecorder {
if !recorder.recording {
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: recorder.url)
audioDuration.maximumValue = Float(audioPlayer!.duration)
_ = NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: #selector(ViewControllerRecorder.updateaudioDuration), userInfo: nil, repeats: true)
audioPlayer?.delegate = self
audioPlayer?.play()
playButton.setImage(UIImage(named: "playing"), forState: UIControlState.Selected)
playButton.selected = true
} catch {
print(error)
}
}
}
}
@IBAction func stop(sender: AnyObject) {
recordButton.setImage(UIImage(named: "record"), forState: UIControlState.Normal)
recordButton.selected = false
playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
playButton.selected = false
stopButton.enabled = false
playButton.enabled = true
audioRecorder?.stop()
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(false)
} catch {
print(error)
}
}
@IBAction func record(sender: AnyObject) {
// Stop the audio player before recording
if let player = audioPlayer {
if player.playing {
player.stop()
playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
playButton.selected = false
}
}
if let recorder = audioRecorder {
if !recorder.recording {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
// Start recording
recorder.record()
recordButton.setImage(UIImage(named: "recording"), forState: UIControlState.Selected)
recordButton.selected = true
} catch {
print(error)
}
} else {
// Pause recording
recorder.pause()
recordButton.setImage(UIImage(named: "pause"), forState: UIControlState.Normal)
recordButton.selected = false
}
}
stopButton.enabled = true
playButton.enabled = false
}
// MARK: - AVAudioRecorderDelegate Methods
func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {
if flag {
// iOS8 and later
let alert = UIAlertController(title: "Recorder",
message: "Finished Recording",
preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Keep", style: .Default, handler: {action in
print("keep was tapped")
}))
alert.addAction(UIAlertAction(title: "Delete", style: .Default, handler: {action in
print("delete was tapped")
self.audioRecorder!.deleteRecording()
}))
self.presentViewController(alert, animated:true, completion:nil)
// let alertMessage = UIAlertController(title: "Finish Recording", message: "Successfully recorded the audio!", preferredStyle: .Alert)
// alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
// presentViewController(alertMessage, animated: true, completion: nil)
print("Audio has finished recording")
print(recorder.url)
}
}
// MARK: - AVAudioPlayerDelegate Methods
func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
playButton.selected = false
let alertMessage = UIAlertController(title: "Finish Playing", message: "Finish playing the recording!", preferredStyle: .Alert)
alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alertMessage, animated: true, completion: nil)
print("Audio has finished playing")
print(player.url)
}
}
ViewControllerFileManager.swift (This is the view controller that I want to display the contents of the document directory to a TableView.)
UPDATED 2016/07/27
import UIKit
class ViewControllerFileManager: UIViewController, UITableViewDataSource, UITableViewDelegate {
var arrayRecordings = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let fileManager = NSFileManager.defaultManager()
let dirPath = NSBundle.mainBundle().resourcePath!
let items = try! fileManager.contentsOfDirectoryAtPath(dirPath)
for item in items {
if item.hasSuffix("m4a") {
arrayRecordings.append(item)
}
print("Found \(item)")
}
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return arrayRecordings.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
// Configure the cell...
cell.textLabel?.text = arrayRecordings[indexPath.row]
return cell
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}