diff --git a/Recordings-MVC/Recordings/FolderViewController.swift b/Recordings-MVC/Recordings/FolderViewController.swift index de4215e..5b5da69 100644 --- a/Recordings-MVC/Recordings/FolderViewController.swift +++ b/Recordings-MVC/Recordings/FolderViewController.swift @@ -21,7 +21,7 @@ class FolderViewController: UITableViewController { NotificationCenter.default.addObserver(self, selector: #selector(handleChangeNotification(_:)), name: Store.changedNotification, object: nil) } - @objc func handleChangeNotification(_ notification: Notification) { + @objc private func handleChangeNotification(_ notification: Notification) { // Handle changes to the current folder if let item = notification.object as? Folder, item === folder { let reason = notification.userInfo?[Item.changeReasonKey] as? String @@ -56,7 +56,7 @@ class FolderViewController: UITableViewController { } } - var selectedItem: Item? { + private var selectedItem: Item? { if let indexPath = tableView.indexPathForSelectedRow { return folder.contents[indexPath.row] } diff --git a/Recordings-MVC/Recordings/PlayViewController.swift b/Recordings-MVC/Recordings/PlayViewController.swift index 91d810b..acfe886 100644 --- a/Recordings-MVC/Recordings/PlayViewController.swift +++ b/Recordings-MVC/Recordings/PlayViewController.swift @@ -1,16 +1,16 @@ import UIKit import AVFoundation -class PlayViewController: UIViewController, UITextFieldDelegate, AVAudioPlayerDelegate { - @IBOutlet var nameTextField: UITextField! - @IBOutlet var playButton: UIButton! - @IBOutlet var progressLabel: UILabel! - @IBOutlet var durationLabel: UILabel! - @IBOutlet var progressSlider: UISlider! - @IBOutlet var noRecordingLabel: UILabel! - @IBOutlet var activeItemElements: UIView! +class PlayViewController: UIViewController { + @IBOutlet private var nameTextField: UITextField! + @IBOutlet private var playButton: UIButton! + @IBOutlet private var progressLabel: UILabel! + @IBOutlet private var durationLabel: UILabel! + @IBOutlet private var progressSlider: UISlider! + @IBOutlet private var noRecordingLabel: UILabel! + @IBOutlet private var activeItemElements: UIView! - var audioPlayer: Player? + private var audioPlayer: Player? var recording: Recording? { didSet { updateForChangedRecording() @@ -27,12 +27,12 @@ class PlayViewController: UIViewController, UITextFieldDelegate, AVAudioPlayerDe NotificationCenter.default.addObserver(self, selector: #selector(storeChanged(notification:)), name: Store.changedNotification, object: nil) } - @objc func storeChanged(notification: Notification) { + @objc private func storeChanged(notification: Notification) { guard let item = notification.object as? Item, item === recording else { return } updateForChangedRecording() } - func updateForChangedRecording() { + private func updateForChangedRecording() { if let r = recording, let url = r.fileURL { audioPlayer = Player(url: url) { [weak self] time in if let t = time { @@ -60,7 +60,7 @@ class PlayViewController: UIViewController, UITextFieldDelegate, AVAudioPlayerDe } } - func updateProgressDisplays(progress: TimeInterval, duration: TimeInterval) { + private func updateProgressDisplays(progress: TimeInterval, duration: TimeInterval) { progressLabel?.text = timeString(progress) durationLabel?.text = timeString(duration) progressSlider?.maximumValue = Float(duration) @@ -68,7 +68,7 @@ class PlayViewController: UIViewController, UITextFieldDelegate, AVAudioPlayerDe updatePlayButton() } - func updatePlayButton() { + private func updatePlayButton() { if audioPlayer?.isPlaying == true { playButton?.setTitle(.pause, for: .normal) } else if audioPlayer?.isPaused == true { @@ -78,24 +78,12 @@ class PlayViewController: UIViewController, UITextFieldDelegate, AVAudioPlayerDe } } - func textFieldDidEndEditing(_ textField: UITextField) { - if let r = recording, let text = textField.text { - r.setName(text) - title = r.name - } - } - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - textField.resignFirstResponder() - return true - } - - @IBAction func setProgress() { + @IBAction private func setProgress() { guard let s = progressSlider else { return } audioPlayer?.setProgress(TimeInterval(s.value)) } - @IBAction func play() { + @IBAction private func play() { audioPlayer?.togglePlay() updatePlayButton() } @@ -118,6 +106,27 @@ class PlayViewController: UIViewController, UITextFieldDelegate, AVAudioPlayerDe self.recording = recording } } + + deinit { + NotificationCenter.default.removeObserver(self) + } + +} + +extension PlayViewController: UITextFieldDelegate { + + func textFieldDidEndEditing(_ textField: UITextField) { + if let r = recording, let text = textField.text { + r.setName(text) + title = r.name + } + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + } fileprivate extension String { diff --git a/Recordings-MVC/Recordings/Player.swift b/Recordings-MVC/Recordings/Player.swift index 5e9919f..d28e92d 100644 --- a/Recordings-MVC/Recordings/Player.swift +++ b/Recordings-MVC/Recordings/Player.swift @@ -1,10 +1,10 @@ import Foundation import AVFoundation -class Player: NSObject, AVAudioPlayerDelegate { - private var audioPlayer: AVAudioPlayer +class Player: NSObject { + private let audioPlayer: AVAudioPlayer private var timer: Timer? - private var update: (TimeInterval?) -> () + private let update: (TimeInterval?) -> () init?(url: URL, update: @escaping (TimeInterval?) -> ()) { do { @@ -46,12 +46,6 @@ class Player: NSObject, AVAudioPlayerDelegate { func setProgress(_ time: TimeInterval) { audioPlayer.currentTime = time } - - func audioPlayerDidFinishPlaying(_ pl: AVAudioPlayer, successfully flag: Bool) { - timer?.invalidate() - timer = nil - update(flag ? audioPlayer.currentTime : nil) - } var duration: TimeInterval { return audioPlayer.duration @@ -69,3 +63,13 @@ class Player: NSObject, AVAudioPlayerDelegate { timer?.invalidate() } } + +extension Player: AVAudioPlayerDelegate { + + func audioPlayerDidFinishPlaying(_ pl: AVAudioPlayer, successfully flag: Bool) { + timer?.invalidate() + timer = nil + update(flag ? audioPlayer.currentTime : nil) + } + +} diff --git a/Recordings-MVC/Recordings/RecordViewController.swift b/Recordings-MVC/Recordings/RecordViewController.swift index bf566dd..c1a975e 100644 --- a/Recordings-MVC/Recordings/RecordViewController.swift +++ b/Recordings-MVC/Recordings/RecordViewController.swift @@ -1,13 +1,12 @@ import UIKit -import AVFoundation -final class RecordViewController: UIViewController, AVAudioRecorderDelegate { - @IBOutlet var timeLabel: UILabel! - @IBOutlet var stopButton: UIButton! +final class RecordViewController: UIViewController { + @IBOutlet private var timeLabel: UILabel! + @IBOutlet private var stopButton: UIButton! - var audioRecorder: Recorder? + private var audioRecorder: Recorder? var folder: Folder? = nil - var recording = Recording(name: "", uuid: UUID()) + private let recording = Recording(name: "", uuid: UUID()) override func viewDidLoad() { super.viewDidLoad() @@ -17,7 +16,7 @@ final class RecordViewController: UIViewController, AVAudioRecorderDelegate { override func viewDidAppear(_ animated: Bool) { super.viewWillAppear(animated) - audioRecorder = folder?.store?.fileURL(for: recording).flatMap { url in + audioRecorder = folder?.store?.fileURL(for: recording).flatMap { [unowned self] url in Recorder(url: url) { time in if let t = time { self.timeLabel.text = timeString(t) @@ -31,7 +30,7 @@ final class RecordViewController: UIViewController, AVAudioRecorderDelegate { } } - @IBAction func stop(_ sender: Any) { + @IBAction private func stop(_ sender: Any) { audioRecorder?.stop() modalTextAlert(title: .saveRecording, accept: .save, placeholder: .nameForRecording) { string in if let title = string { diff --git a/Recordings-MVC/Recordings/Recorder.swift b/Recordings-MVC/Recordings/Recorder.swift index e698081..c8a52b5 100644 --- a/Recordings-MVC/Recordings/Recorder.swift +++ b/Recordings-MVC/Recordings/Recorder.swift @@ -1,11 +1,11 @@ import Foundation import AVFoundation -final class Recorder: NSObject, AVAudioRecorderDelegate { +final class Recorder: NSObject { private var audioRecorder: AVAudioRecorder? private var timer: Timer? - private var update: (TimeInterval?) -> () - let url: URL + private let update: (TimeInterval?) -> () + private let url: URL init?(url: URL, update: @escaping (TimeInterval?) -> ()) { self.update = update @@ -50,7 +50,11 @@ final class Recorder: NSObject, AVAudioRecorderDelegate { audioRecorder?.stop() timer?.invalidate() } - + +} + +extension Recorder: AVAudioRecorderDelegate { + func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { if flag { stop() @@ -58,4 +62,5 @@ final class Recorder: NSObject, AVAudioRecorderDelegate { update(nil) } } + } diff --git a/Recordings-MVC/Recordings/Store.swift b/Recordings-MVC/Recordings/Store.swift index ce8defa..4c4272a 100644 --- a/Recordings-MVC/Recordings/Store.swift +++ b/Recordings-MVC/Recordings/Store.swift @@ -5,7 +5,7 @@ final class Store { static private let documentDirectory = try! FileManager.default.url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: true) static let shared = Store(url: documentDirectory) - let baseURL: URL? + private let baseURL: URL? var placeholder: URL? private(set) var rootFolder: Folder diff --git a/Recordings-MVC/Recordings/Utilities.swift b/Recordings-MVC/Recordings/Utilities.swift index 1ad8eaf..b55809b 100644 --- a/Recordings-MVC/Recordings/Utilities.swift +++ b/Recordings-MVC/Recordings/Utilities.swift @@ -20,7 +20,7 @@ extension UIViewController { alert.addAction(UIAlertAction(title: cancel, style: .cancel) { _ in callback(nil) }) - alert.addAction(UIAlertAction(title: accept, style: .default) { _ in + alert.addAction(UIAlertAction(title: accept, style: .default) { [unowned alert] _ in callback(alert.textFields?.first?.text) }) present(alert, animated: true)