Hi! I am trying to build an app for band kids to record practice sessions to cloudKit on one viewController & display sessions on a UITableview with the option to play the audio & email the session to a teacher. None of my audio is saving when I try it on my iPhone or displaying, here is the code I have, I have iCloud set up from Capabilities & a container checked. Thank you!
ViewController for recording sessions:
import UIKit
import CoreData
import AVFoundation
class NewPracticeSessionViewController: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate, UITextFieldDelegate {
var audioRecorder: AVAudioRecorder?
var audioPlayer: AVAudioPlayer?
var recordingSession: AVAudioSession!
@IBOutlet weak var startRecording: UIButton!
@IBOutlet weak var endRecording: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
func setupView() {
let format = DateFormatter()
format.dateFormat = "MM-dd-yyyy"
let currentFileName = "recording-\(format.string(from: NSDate() as Date)).caf"
print(currentFileName)
recordingSession = AVAudioSession.sharedInstance()
do {
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Error on setting up the recorder: \(error.localizedDescription)")
}
startRecording.isEnabled = false
endRecording.isEnabled = true
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
func loadRecordingUI(){
startRecording.isEnabled = true
startRecording.setTitle("Recording", for: .normal)
startRecording.addTarget(self, action: #selector(setter: startRecording), for: .touchUpInside)
view.addSubview(startRecording)
}
func beginRecording() {
if audioPlayer != nil && ((audioPlayer?.isPlaying) != nil) {
audioPlayer?.stop()
}
if audioRecorder == nil {
let audioFileName =
getDocumentsDirectory().appendingPathComponent("recording.m4a")
print("Recording saved at: "+audioFileName.absoluteString)
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
audioRecorder = try AVAudioRecorder(url: audioFileName, settings: settings)
audioRecorder?.delegate = self
audioRecorder?.isMeteringEnabled = true
audioRecorder?.record()
startRecording.setTitle("Now Recording", for: .normal)
} catch {
finishRecording(success: false)
}
} else {
finishRecording(success: true)
}
}
func finishRecording(success: Bool) {
audioRecorder?.stop()
audioRecorder = nil
if success {
print("Recording successful completed")
} else {
print("Recording Failed")
}
self.performSegue(withIdentifier: "Already Completed", sender: self)
}
@IBAction func startRecording(_ sender: UIButton) {
beginRecording()
}
@IBAction func endRecording(_ sender: UIButton) {
finishRecording(success: true)
func saveTrack(asset: AVURLAsset) {
let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A)
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
exporter?.outputURL = fileURL
exporter?.exportAsynchronously(completionHandler: {
print(exporter?.status)
print(exporter?.estimatedOutputFileLength)
print(exporter?.maxDuration)
print("Finished Saving File")
})
}
}
UITableView where the saved audio files are displayed, played and emailed:
import UIKit
import AVFoundation
import CloudKit
import CoreData
class ExistingPracticeSessionsTableViewController: UITableViewController, URLSessionDelegate {
var receivedAudio: URL?
var practiceRecordings = [String]()
var player: AVAudioPlayer?
var audioUrl: String = ""
var arrayRecordings = [URL]()
var fileName = "audio_file.m4a"
override func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
listRecordings()}
func listRecordings() {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
do {
let urls = try FileManager.default.contentsOfDirectory(at: documentsDirectory, includingPropertiesForKeys: nil, options: FileManager.DirectoryEnumerationOptions.skipsHiddenFiles)
self.arrayRecordings = urls.filter({ (name: URL) -> Bool in
return name.lastPathComponent.hasSuffix("m4a")
})
} catch let error as NSError {
print(error.localizedDescription)
} catch {
print("Something went wrong listing recordings")
}
}
func playSound(url: URL) {
print("playing\(url)")
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
self.player = try AVAudioPlayer(contentsOf: url)
player?.play()
} catch let error {
print(error.localizedDescription)
}
}
func getCacheDirectory() -> URL {
let fm = FileManager.default
let docsurl = try! fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
return docsurl
}
func getFileURL() -> URL {
let path = getCacheDirectory()
let filePath = path.appendingPathComponent("\(fileName)")
return filePath
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return practiceRecordings.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
cell.textLabel?.text = practiceRecordings[indexPath.row]
listRecordings()
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print(practiceRecordings[indexPath.row])
}